腾讯应用宝米大师直购模式支付流程以及服务端php回调校验

2023-11-12

一. 米大师简介

1.米大师(Midas)为腾讯官方唯一虚拟支付平台。

2.YSDK已经内置了米大师(Midas)支付模块,游戏开发者接入YSDK后,可以通过相应的配置开启米大师的支付功能,并调用YSDK已经封装好的接口,即可快速实现支付能力。目前已支持微信支付(wechat)、QQ钱包(qqwallet)两种支付渠道。

3.米大师(Midas)目前支持直接购买道具(直购模式)、游戏币、游戏币+直接购买道具三种模式,本文重点介绍直购模式,其他支付模式请参考该文档。

二. 直购模式介绍

2.1 计费信息介绍及填写

计费信息名称

介绍/填写说明

模式含义

直接购买道具或服务(直接购买道具礼包,通过回调接口游戏方自己发货)。

支持游戏类型

联运网游/单机类型均可支持。

配置路径

(1)通过“腾讯应用开放平台-基础服务-支付管理-计费接入”该路径。

(2)通过“腾讯应用开放平台-基础服务-SDK接入-YSDK支付信息配置”该路径。

支付权限获取

沙箱环境:需在”腾讯开放平台-支付结算-计费接入“发布沙箱成功后,即可获得沙箱环境支付权限。

现网环境:需在”腾讯开放平台-支付结算-计费接入“发布现网成功后,即可获得现网环境支付权限。

注意事项:

1)游戏配置计费信息时,需先配置并调试沙箱环境成功,再配置并调试现网环境,具体参考配置米大师计费信息配置步骤指引。

2)请勿在沙箱环境调试现网环境支付信息,同时也请勿在现网环境调试沙箱环境支付信息,否则会提示无支付权限(报错码为1016-1016-0)。

应用计费ID

游戏创建时会自动分配,接入计费时平台自动拉取,无需填写。

应用名称

该应用名称米大师用来标识业务,需和创建时名称一致。

支付展示应用名称

该应用名称为游戏内支付时显示的游戏名称、及玩家充值成功后交易记录中所显示游戏名称。

支付模式

选择“直接购买道具”。

托管类型

(1)需先选择支付模式为“直接购买道具”,才会展示发货托管类型选择项。

(2)外部服务器:

腾讯云服务器:若游戏使用腾讯云服务器,IP地址非基础网络,需选择外部服务器,并下载安装米大师证书。

非腾讯云服务器:比如阿里云、华为云服务器等,需选择外部服务器,并下载安装米大师证书。

注意事项:

以上两种服务器,回调地址配置时,均需使用“https”协议和“443”接口。

回调接口

(1)多款游戏不支持回调接口共用。

(2)沙箱和现网回调接口不支持共用。

(3)回调接口配置详细步骤需参考米大师计费信息配置文档。

米大师证书

(1)下载路径:回调接口管理-接口证书-下载。

(2)沙箱和现网米大师CA证书不支持共用。

(3)米大师证书安装需参考米大师CA证书配置说明文档。

(4)证书有效期:现网证书10年,沙箱证书1年,建议到期前及时更换,更换时需重新下载证书进行配置。

2.2 计费信息变更

计费信息名称

变更说明

应用计费ID(offerid)

游戏创建时自动分配,接入计费时平台自动拉取,无需变更。

应用名称

建议游戏在沙箱环境确认好应用名称,在应用宝平台首发后不支持变更。

支付展示应用名称

建议游戏在沙箱环境确认好支付展示应用名称,在应用宝平台首发后不支持变更。

支付模式

(1)修改为游戏币模式,仅支持在应用宝平台首发前变更。

(2)修改为游戏币+直购模式,仅支持在应用宝平台首发前变更,且一旦变更为游戏币+直购模式,发布现网后不可回退为直购模式。

回调地址

仅支持游戏首发应用宝平台前变更,若特殊原因需更换线上游戏回调发货地址,需联系应用宝客服或商务报备申请。

线上游戏新增计费点

直购物品id价格是业务侧自定义的,线上游戏新增计费点配置后,需发布现网调试成功即可。

2.3 支付流程示意图

服务器端下单流程:

客户端下单流程:

(1) 成功发货

条件一:在游戏接入平台创建新应用时,在分区配置中配置了回调接口URL,URL用于提供给腾讯后台回调。用户付费成功后,腾讯后台将回调该URL通知业务发货。

条件二:开发者需按照《回调发货URL的协议说明》进行发货URL的开发,收到米大师的回调后必须2s内返回{“ret":0,"msg":"OK"}才认为时发货成功。

(2) 发货失败

由于网络等原因可能回调业务失败,米大师有以下三种重试机制:

微信支付渠道:不退款,24小时内总共会发起15次通知,通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h

QQ钱包:不退款,2小时内重试9次(15s/15s/30s/180s/1800s/1800s/1800s/1800s/3600s)

Q币、Q卡:回调发货失败5分钟后会退款。

三. 直购模式准备工作

1. 填写基本资料

直购模式不需要配置兑换比例,但必须配置回调接口,本环节重点介绍托管类型选择、回调接口配置、米大师证书安装说明;基本信息、分区介绍可参考游戏币模式填写说明。

1.1 托管类型

外部服务器

注:外部服务器,指非腾讯云和腾讯自研的其他服务器,比如阿里云、华为云服务器等。

2. 回调接口

注:沙箱和现网回调接口不可以使用同一个,且多个游戏也不可以使用同一个发货地址。

3.米大师证书下载安装

米大师证书必须先新增沙箱或现网接口后才会显示下载入口,沙箱和现网配置步骤相同,以沙箱环境为例,如下图:

注意:

(1)使用外部托管类型的游戏必须安装米大师证书。

(2)目前腾讯云(DEV)服务器已不支持基础网络,所以使用腾讯云(DEV)服务器的,均需要选择https协议,同时也需要安装下载米大师证书。

(3)直购模式下,腾讯云服务器回调接口和米大师证书下载安装步骤请参考上述步骤。

(4)沙箱和现网的证书不可共用,需各自使用对应环境下载的证书。

(5)多个游戏不可使用同一个米大师证书。

(6)回调发货协议说明请参考米大师文档

三. 直购模式客户端接入

1. 直购支付流程图

服务器下单流程:

客户端下单流程:

2. 概述

直购模式支持单机和网游游戏。

客户端下单模式是指用户直接通过下述api调用唤起腾讯支付页面引导用户完成付费,用户付费结束后,结果会通过参数重的YSDKPayListener回调给游戏,同时米大师会调用游戏在米大师配置的回调地址发货。

3. 请求参数

参数名称

描述

iscanchange

是否可以在拉起的支付页面进行变更

zoneid

分区id

item

支付项

item.id

游戏内自定义的道具id

Item.name

道具的名称,支付时会显示在支付页面上

Item.desc

道具描述

Item.price

道具单价,单价以Q点(角)为单位

Item.num

购买数量,在支付页面上不可修改

item.unit

物品单位

midasAppkey

游戏中米大师的appkey。

注:沙箱用沙箱的appkey,现网用现网的appkey.

resData

游戏代币图标的二进制数据

midasExt

米大师透传参数,会调用发货接口时透传给游戏

ysdkExtInfo

YSDK透传参数,会在listener中回调给游戏

listener

充值回调

4. 请求示例

String zoneId = "1";

PayItem item = newPayItem();

item.id = "ID1";

item.name = "道具名称";

item.desc = "道具描述";

item.price = 1;

item.num = 5;

item.unit= "道具单位";

Bitmap bmp = BitmapFactory.decodeResource(mMainActivity.getResources(), R.drawable.sample_yuanbao);

ByteArrayOutputStream baos = newByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] appResData = baos.toByteArray();

String ysdkExt = "ysdkExt"; String midasExt = "midasExt";

YSDKApi.buyGoods(false,zoneId,item,"sdsfdsfdf",appResData,midasExt,ysdk Ext,newPayListener() {

@Override

publicvoidOnPayNotify(PayRet ret) { if(PayRet.RET_SUCC == ret.ret){

//⽀付流程成功

switch(ret.payState){

//⽀付成功

casePayRet.PAYSTATE_PAYSUCC: mMainActivity.sendResult(

"⽤户⽀付成功,⽀付⾦额"+ret.realSaveNum+";"+

"使⽤渠道:"+ret.payChannel+";"+ "发货状态:"+ret.provideState+";"+ "业务类型:"+ret.extendInfo+";建议查询余

额:"+ret.toString());

break;

//取消⽀付

casePayRet.PAYSTATE_PAYCANCEL: mMainActivity.sendResult("⽤户取消⽀

付:"+ret.toString());

break;

//⽀付结果未知

casePayRet.PAYSTATE_PAYUNKOWN: mMainActivity.sendResult("⽤户⽀付结果未知,建议查询余

额:"+ret.toString());

break;

//⽀付失败

casePayRet.PAYSTATE_PAYERROR: mMainActivity.sendResult("⽀付异常"+ret.toString()); break;

}

}else{

switch(ret.flag){

caseeFlag.User_LocalTokenInvalid:

//⽤户取消⽀付 mMainActivity.sendResult("登陆态过期,请重新登

陆:"+ret.toString());

mMainActivity.letUserLogout(); break;

caseeFlag.Pay_User_Cancle:

//⽤户取消⽀付 mMainActivity.sendResult("⽤户取消⽀

付:"+ret.toString());

break;

caseeFlag.Pay_Param_Error: mMainActivity.sendResult("⽀付失败,参数错

误"+ret.toString());

break;

}

5. 返回参数

参数名称

描述

Ret

0成功1失败

flag

0成功非0失败

msg

ret不为0的时候,错误信息(utf-8编码)

注意事项:

支付不以客户端的结果为准。

四.直购模式服务端下单接入

1. 概述

直购模式分为服务器下订单和客户端下订单两种。 客户端下订单请参考客户端接入

2. 服务端下单模式

服务器下单模式是指游戏应⽤开发者在游戏中调⽤如下接⼝执⾏订单操作,获取到⽀付服务器返回的订单url

现⽹:https://ysdk.qq.com/mpay/buy_goods_m

沙箱:https://ysdktest.qq.com/mpay/buy_goods_m

3. 请求参数

3.1 Cookie参数

参数名称

描述

session_id

用户账户类型,(手Q)session_id ="openid";(微信)session_id = "hy_gameid"

session_type

session类型,(手Q)session_type = "kp_actoken";(微信)session_type = "wc_actoken"

org_loc

需要填写: /v3/r/mpay/buy_goods_m (注意:如果经过接口机器,需要填写应用签名时使用的URI)

appip

(可选)来源的第三方应用的服务IP

注意事项:

cookie里面org_loc的值,需要进行urlencode,如果使用开平提供的 OpenAPI V3.0 SDK 计算签名,org_loc不需要进行urlencode,因为sdk已经在内部做了编码。

session_id中openid为固定的字符串字段,并非登录成功后获取的openid

游客登陆为

session_id="hy_gameid"

session_type="st_dummy"

3.2 请求参数

参数名称

描述

openid

从手Q登录态中获取的openid的值

openkey

手Q登陆时传手Q登陆回调里获取的paytoken值,微信登陆时传微信登陆回调里获取的传access_token值。游客登陆传openkey

appid

应用的唯一ID。可以通过appid查找APP基本信息。

ts

UNIX时间戳(从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数)。

pf

平台来源,参考公共参数说明。

pfkey

跟平台来源和openkey根据规则生成的一个密钥串。如果是腾讯自研应用固定传递pfkey=”pfkey”

zoneid

账户分区ID。应用如果没有分区:传zoneid=1

payitem

请使用x*p*num的格式,x表示物品ID,p表示单价(以Q点为单位,1Q币=10Q点,单价的制定需遵循腾讯定价规范),num表示默认

的购买数量。(格式:物品ID1*单价1*建议数量1,批量购买物品时使用;分隔,如:id1*price1*num1;id2*price2*num2)长度必<=512

goodsmeta

物品信息,格式必须是“name*des”,批量购买套餐时也只能有1个道具名称和1个描述,即给出该套餐的名称和描述。name表示物品的

名称,des表示物品的描述信息。用户购买物品的确认支付页面,将显示该物品信息。长度必须<=256字符,必须使用utf8编码。目前

goodsmeta超过76个字符后不能添加回车字符。

goodsurl

物品的图片url(长度<512字符)

sig

请求串的签名,参考YSDK支付接口签名说明

amt

(可选)道具总价格。(amt必须等于所有物品:单价*建议数量的总和 单位为1Q点)

max_num

(可选) 用户可购买的道具数量的最大值。仅当appmode的值为2时,可以输入该参数。输入的值需大于参数“payitem”中的num,如果

小于num,则自动调整为num的值。

appmode

(可选)1表示用户不可以修改物品数量,2 表示用户可以选择购买物品的数量。默认2(批量购买的时候,必须等于1)

app_metadata

(可选)发货时透传给应用。长度必须<=128字符

userip

(可选)用户的外网IP

format

(可选)json、jsonp_$func。默认json。如果jsonp,前缀为:$func

例如:format=jsonp_sample_pay,返回格式前缀为:sample_pay()

sp_info

(可选)传code_id,batch_id,道具模式下单后台传抵扣券ID

以下参数只有走订单

中心情况下需要传,

其他情况不传

out_trade_no

订单号

goods_tag

新增字段.表示微信订单优惠标记.

透传给微信,格式参考:https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_102&index=2 对应的goods_tag字段

wx_goods_detail

新增字段.表示微信商品详情信息.需要对内容urlencode.(最大长度是encode前的长度)

透传给微信,格式参考:https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_102&index=2 对应的detail字段

4. 请求示例

curl "http://IP:端口/v3/r/mpay/buy_goods_m?appid=1450001088&openid=odFzSjlSIm09-35bPDeHrwzO1rqU&openkey=

35_c79HmE4aWyrmrIuq6p6lMelVzG4pqMSNobfqDUON9SYixKJyVBO4YwGCMURygpYRFU3_7PPJbkkKVXpIRDDHe323Bp_WPDeG-23XVB_

QGqI&ts=1596180606&pf=desktop_m_qq-1001-android-73213123-qq-1107898689-0AC547EC71BCCED71594AA1A97177675&pfkey

=cd517e6bb043504da99906e5e99a6c87&zoneid=1&payitem=1711*1*1&goodsmeta=test*test&out_trade_no=20200313001&sig=

4+UTHzcgJwn1bzj8nQO3KQY+WSw=" -b "session_id=hy_gameid;session_type=wc_actoken;org_loc=/v3/r/mpay/buy_goods_m"

5. 道具直购客户端接口 (服务器下单)

该接口用于通过后台服务器下单的道具直购场景,游戏调用接口以后唤起腾讯支付页面引导用户完成付费,用户付费结束以后,结果会通过参数中的YSDKPayListener回调给游戏,同时米大师会调用游戏在米大师配置的回调地址发货。

5.1 接口声明

参数名称

描述

zoneId

大区id

goodsTokenUrl

后台下订单返回的urlPara

resData

代币图标的二进制数据

ysdkExtInfo

YSDK透传参数,会在listener中回调给游戏

listener

充值回调

5.2 请求示例

voidbuyGoods(String zoneId, String goodsTokenUrl, byte[] resData, String ysdkExtInfo, PayListener listener);

5.3 接口调用

String zoneId = "1";

String goodsTokenUrl ="/v1/xs1/110***6059/mobile_goods_info?token_id=211FB8F9199683F*****E6B355A3422123";

Bitmap bmp = BitmapFactory.decodeResource(mMainActivity.getResources(), R.drawable.sample_yuanbao);

ByteArrayOutputStream baos = newByteArrayOutputStream();

bmp.compress(Bitmap.CompressFormat.PNG, 100, baos);

byte[] appResData = baos.toByteArray();

String ysdkExt = "ysdkExt";

voidbuyGoods(zoneId, goodsTokenUrl,appResData,ysdkExt,newPayListener() {

@Override

publicvoidOnPayNotify(PayRet ret) {

if(PayRet.RET_SUCC == ret.ret){

//支付流程成功

switch(ret.payState){

//支付成功

casePayRet.PAYSTATE_PAYSUCC:

mMainActivity.sendResult(

"用户支付成功,支付金额"+ret.realSaveNum+";"+

"使用渠道:"+ret.payChannel+";"+

"发货状态:"+ret.provideState+";"+

"业务类型:"+ret.extendInfo+";建议查询余额:"+ret.toString());

break;

//取消支付

casePayRet.PAYSTATE_PAYCANCEL:

mMainActivity.sendResult("用户取消支付:"+ret.toString());

break;

//支付结果未知

casePayRet.PAYSTATE_PAYUNKOWN:

mMainActivity.sendResult("用户支付结果未知,建议查询余额:"+ret.toString());

break;

//支付失败

casePayRet.PAYSTATE_PAYERROR:

mMainActivity.sendResult("支付异常"+ret.toString());

break;

}

}else{

switch(ret.flag){

caseeFlag.User_LocalTokenInvalid:

//用户取消支付

mMainActivity.sendResult("登陆态过期,请重新登陆:"+ret.toString());

mMainActivity.letUserLogout();

break;

caseeFlag.Pay_User_Cancle:

//用户取消支付

mMainActivity.sendResult("用户取消支付:"+ret.toString());

break;

caseeFlag.Pay_Param_Error:

mMainActivity.sendResult("支付失败,参数错误"+ret.toString());

break;

caseeFlag.Error:

default:

mMainActivity.sendResult("支付异常"+ret.toString());

break;

}

}

}

});

6. 返回参数

参数名称

描述

ret

返回码0:成功, >=1000:失败

msg

ret不为0的时候,错误信息(utf-8编码)。

token

ret为0的时候,开发者需要保留。后续扣费成功后调用第三方发货时,会再传给开发者,作为本次交易的标识。

url_params

ret为0的时候,返回真正购买物品的url的参数,开发者需要把该参数传给sdk跳转到相关页面使用户完成真正的购买动作。

五.直购模式客户端下单案例

1.前端拉起商品列表

用户登录app后,进入商品购买页面,前端请求app商品列表api接口,获取商品列表信息并展示

2.下单

用户点击'购买'操作,发送给服务端一条当前商品信息,服务端保存该商品的相关订单数据,并返回给前端腾讯米大师支付所需要的请求数据,前端调用米大师支付sdk,发起支付请求
    /**
     * 腾讯应用宝米大师支付下单
     * @param array $params 订单信息
     * @return array
     */
    public static function Pay($params)
    {
        //获取商品内部订单号
        $innerOno = self::genInnerOno(date("Y-m-d H:i:s"), $params['user_id'], $paymentType);
        //生成订单
        $order = new Order();
        $order->order_id = $innerOno;  // 内部订单号
        $order->product_name = $params['name'];  // 商品名称
        $order->number = $params['num'];  // 购买商品个数
        $order->price = $params['price'];  // 商品单价, 1个商品价格
        $order->total_price = $params['total_price'];  // 总的价格
        $order->pay_amount = $params['pay_amount'];  // 应付总额:  实际应该支付的价格= 总金额 - 优惠金额
        $order->count = $params['count'];  // 购买后得到商品对应的产品数量
        $order->status = 0;  // 状态:0 待支付     
        $order->user_id = $params['user_id'];  // 用户游戏ID
        $order->expired_at = $params['expired_at'];  // 过期时间
        $order->created_by = $params['created_by'];  // 创建者
        $order->updated_by = $params['updated_by'];  // 创建者
 
        $result = $order->save();
        if (!$result) {
            $errors = '';
            if ($order->hasErrors()) {
                $tmp = $order->getErrors();
                foreach ($tmp as $rows) {
                    foreach ($rows as $row) {
                        $errors .= $row . '<br/>';
                    }
                }
            }
            throw new \Exception($errors);
        }
        $orderId = $order->id;
        
        //构建vivo支付所需要的数据
        $title = $order->product_name;
        //过滤掉特殊字符
        $title = replaceStr($title);
        $config = Yii::$app->params['tencent.app']; //腾讯应用宝配置
        $price = intval($model->pay_amount * 10);
        //游戏中米大师的appkey,沙箱用沙箱的appkey,现网用现网的appkey.
        $midasAppkey = $config['tx_midas_is_sandbox'] == 1 ? $config['tx_midas_sandbox_app_key'] : $config['tx_midas_now_app_key'];
 
        //构建向应用宝发送的参数
        $data = [
            'iscanchange' => false, //是否可以在拉起的支付页面进行变更
            'zoneid' => 1,  //分区id
            'id' => $model->order_id,  //游戏内自定义的道具id
            'name' => $title,  //道具的名称,支付时会显示在支付页面上
            'desc' => $title,  //道具描述
            'price' => $price,  //道具单价,单价以Q点(角)为单位
            'num' => 1,  //购买数量,在支付页面上不可修改
            'unit' => '个',  //物品单位
            'midasAppkey' => $midasAppkey,  //游戏中米大师的appkey,注:沙箱用沙箱的appkey,现网用现网的appkey.
            'midasExt' => 'midasExt',  //米大师透传参数,会调用发货接口时透传给游戏
            'ysdkExtInfo' => 'ysdkExtInfo',  //YSDK透传参数,会在listener中回调给游戏
        ];
 
        return jsonFail($data);
    }
 
   /**
     * 生成本系统内部订单号, 在向第三方服务商发起支付时需要使用.
     *
     * 下单时的处理流程:
     *   1. 属性 ono 不要赋值, 成功插入(保存)订单.
     *   1. 支付前生成本系统内部订单号, 向第三方发起支付请求.
     *   1. 接收到支付成功回调通知时, 将第三方订单号保存到本次付款的订单的 ono 字段上.
     *
     * 格式: 下单时间+支付方式+ 4位数字修正值. 如 "20150930140041+1+1234".
     * 最大长度 32 个字符. 这也是 wx 可接受的订单号最大长度.
     *
     * @param int $createdAt 订单创建时间戳, 即 下单时间戳.
     * @param int $createdBy 订单创建人 ID, 即 下单会员 ID.
     * @return string
     * @throws \Exception
     */
 
    public static function genInnerOno($createdAt, $createdBy)
    {
        $createdAt = strtotime($createdAt);
        if (1 > $createdAt || 1 > $createdBy) {
            throw new \Exception('参数错误');
        }
 
        // 生成一个修正值, 一定程度上增加订单号的随机性.
        $tmp = intval(substr($createdAt, -4)) + intval(substr($createdBy, -2));
        if (4 < strlen($tmp)) {
            $tmp = substr($tmp, -4);
        }
 
        $tmp = date('YmdHis', $createdAt) . $tmp . rand(100, 900);
        return $tmp;
    }

3. 支付

前端获取服务端返回的支付所需要的请求数据后,拼接支付请求参数,调用米大师支付sdk,发起支付请求

4. 回调操作

前端支付成功后,米大师会请求服务端的回调方法( 三. 直购模式准备工作中的配置步骤),对支付订单进行校验验签操作,根据验签结果,处理订单业务逻辑
php以yii2框架为参考
    /**
     * 腾讯应用宝支付回调处理: 异步回调操作: 主动请求多次, 用于处理商家订单状态等逻辑操作
     */
    public function actionNotify()
    {
        /获取回调通知数据
        $inBodyArray = $_GET;

        //判断通知请求
        $trans = Yii::$app->db->beginTransaction();
        try {
            //引入米大师SDK
            $dir = Yii::getAlias('@common/lib/tenxun/PHP_SDK_V3.0.9');
            require_once $dir . '/lib/SnsSigCheck.php';
            //签名校验
            $config = Yii::$app->params['tencent.app'];
            //获取AppKey
            $midasAppkey = $config['tx_midas_is_sandbox'] ? $config['tx_midas_sandbox_app_key'] : $config['tx_midas_now_app_key'];
            $checkSign = \SnsSigCheck::verifySig('GET', '/notify', $inBodyArray, $midasAppkey . '&', $inBodyArray['sig']);
            if ($checkSign) { //处理业务逻辑
                $cftid = $inBodyArray["cftid"]; //财付通订单号
                $payitem = $inBodyArray['payitem'];//物品信息
                $payitem = explode("*", $payitem);
                $order_id = $payitem[0]; //
                // 订单状态
                $status = UserOrder::STATUS_BUY;

                //判断订单状态是否已经支付
                $userOrder = UserOrder::find()->where(['status' => $status, 'deal_number' => $innerOno])->exists();
                if ($userOrder) {
                    throw new \Exception('订单已支付');
                }
                // 变更订单属性
                UserOrder::changeAttribute(
                    ['order_id' => $order_id],
                    [
                        'status' => $status,
                        'paid_at' => time(), //支付时间
                        'cftid' => $cftid,
                    ]
                );

                $trans->commit();
                //返回给客户端数据,客户端会根据该结果处理米大师中该订单状态
                $result = [
                    'ret' => 0,
                    'msg' => 'OK',
                ];
            } else {
                throw new \Exception('签名校验失败');
            }
        } catch (\Exception $e) {
            $result = [
                'ret' => -5,
                'msg' => $e->getMessage(),
            ];
         
            $trans->rollBack();
        }
        echo json_encode($result);
    }

5.上面需要使用到的公共方法

/**
 * 操作成功
 * @example1 jsonSuccess();
 */
function jsonSuccess($data = NULL, $message = '操作成功')
{
    header("Content-Type:application/json");
    $json = array();
    $json['code'] = 0;
    $json['data'] = $data;
    $json['message'] = $message;
    $json['request_time'] = now();
    echo Json::encode($json);
    exit();
}

/**
 * 错误信息
 * @example1 jsonFail();
 * @example1 jsonFail("删除失败!");
 * @example2 jsonFail($model->getErrors());
 */
function jsonFail($message = '请求失败', $code = 1, $data = null)
{
    header("Content-Type:application/json");
    $json = array();
    $json['code'] = $code;
    $json['data'] = $data;
    $json['message'] = $message;
    $json['request_time'] = now();
    echo Json::encode($json);
    exit();
}

/**
 * 过滤掉特殊的字符
 * @param $str
 * @param string $replacement
 * @return string|string[]|null
 */
function replaceStr($str, $replacement = '')
{
    $regex = "/\/|\~|\,|\。|\!|\?|\“|\”|\【|\】|\『|\』|\:|\;|\《|\》|\’|\‘|\ |\·|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\+|\{|\}|\:|\<|\>|\?|\[|\]|\,|\.|\/|\;|\'|\`|\-|\=|\\\|\|/";
    $result = preg_replace($regex, $replacement, $str);

    return $result;
}
Yii2 腾讯应用宝米大师相关配置:params-local.php
<?php

return [
     //腾讯应用宝
    'tencent.app' => [
        //腾讯应用平台,米大师沙箱,现网
        'tx_midas_is_sandbox' => 1,
        //腾讯应用平台,米大师沙箱AppKey
        'tx_midas_sandbox_app_key' => 'xxx',
        //腾讯应用平台,米大师现网AppKey
        'tx_midas_now_app_key' => 'xxx',
        'pay_test' => 1, //是否支付测试
        'is_screen_pay' => 0, //是否屏蔽支付
    ],
];
腾讯应用宝米大师支付SDK下载:链接: https://pan.baidu.com/s/1o93e9IkRajVzwwSI1Z3Lkg 提取码: sko1

参考文档:

YSDK介绍:https://wikinew.open.qq.com/index.html#/iwiki/847226339

米大师国内标准版: https://wiki.midas.qq.com/post/index/1/45/82/0

SDK下载文档:https://wikinew.open.qq.com/index.html#/iwiki/877913496

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

腾讯应用宝米大师直购模式支付流程以及服务端php回调校验 的相关文章

  • PHP - hash_pbkdf2 函数

    我正在尝试使用此 php 函数执行一个函数来哈希密码 http be php net manual en function hash pbkdf2 php http be php net manual en function hash pb
  • PHP7构造函数类名

    我有一个 Laravel 4 2 应用程序 它可以与 PHP5 一起使用 没有任何问题 由于我安装了一个运行 PHP7 的新 vagrant box 一旦我运行一个模型 其中函数名称与类名称 关系函数 相同 就会出现错误 如下所示
  • 未捕获的异常“Google_IO_Exception”,消息为“HTTP 错误:无法连接”

    我有一个任务 查询 运行一些从 gmail 邮箱检索数据的 php 代码 直到上周五 2015 年 4 月 10 日 它一直工作正常 现在我收到以下错误日志 E 11 58 26 094 2015 04 15 200 3 38 KB 14
  • 在 Woocommerce 购物车中设置最小小计金额

    我正在尝试将最低订单金额设置为 25 美元 到目前为止 我找到了这段代码 如果未达到最低限度 它似乎可以阻止结账 但它使用的小计包含税费 我需要在总计中排除税费 add action woocommerce checkout process
  • PHP中如何识别服务器IP地址

    PHP中如何识别服务器IP地址 对于服务器 ip 来说是这样的 SERVER SERVER ADDR 这是港口的 SERVER SERVER PORT
  • 如何在php中使用preg添加html属性

    我正在寻找在 php 中编写一个脚本来扫描 html 文档并根据它找到的内容向元素添加新标记 更具体地说 我是扫描文档并为每个元素搜索CSS标记 float right left 如果找到它 它会添加align right left 基于它
  • PHP文件上传

    如果我想在文件名转到服务器的永久位置 而不是临时位置 之前更改文件名 我该如何执行此操作 代码如下
  • 如何将粘在一起的单词分开?

    我有很多命名不好的文件 videoofmegoingtoschool avi 是否有一个库或某种算法可以正确地将其分离 video of me going to school avi 我不认为那里有什么 我可以想象一个程序 它使用单词词典并
  • 来自本地 XML 的模拟 SoapClient 响应

    我想用文件中的 XML 来模拟 SoapClient 的响应 我如何创建一个 stdClass 对象 就像 SoapClient 从文件返回一样 客户端已经包装了 SoapClient 因此可以轻松模拟响应 我的模拟是这样的 soapCli
  • Laravel 5.4 升级 - 违反完整性约束 - 列不能为空

    奇怪的是 所有这些都在 5 2 中工作 但我不知道可以改变什么来实现这一点 下面是错误和正在插入的数组 SQLSTATE 23000 Integrity constraint violation 1048 Column gender can
  • 将数据库中的用户 ID 添加到 Codeigniter 中的会话数据中?

    我是 CodeIgniter 的新手 在从数据库添加用户 ID 用户登录后 到会话数据时遇到问题 这是我的代码问题 之前可能会在 SOF 上被问到 在付出了所有努力之后 我问这个 登录模型
  • 尝试获取 Google accessToken

    看起来 无论我做什么 谷歌都在竭尽全力阻止我完成这个研究项目 我的项目让我使用 Google 电子表格作为数据库 并使用所述电子表格中的数据执行程序化的 Google 图片搜索 并向最终用户显示一些结果 设置说明 我开始按照此处的说明进行操
  • PHP使用auto_increment生成短唯一ID?

    我想生成一个简短的 唯一的 ID 而不必检查冲突 我目前正在做类似的事情 但是我当前生成的 ID 是随机的 并且在循环中检查冲突很烦人 并且如果记录数量显着增加 将会变得昂贵 通常担心冲突不是问题 但我想要生成的唯一 ID 是一个由 5 8
  • Doctrine 1 和 Symfony 1 的多个主键?

    我已经知道在 Symfony 1 和 Doctrine 1 中不可能使用多个主键 但是你们知道有什么好的解决方法吗 除了多对多关系之外 原则 1 不适用于多列上的主键 但如果你想使用多对多关系 请像这样使用 BlogPost columns
  • 如何让Gmail像加载进度条一样

    我想在页面的中心和顶部创建一个像 Gmail 一样的加载进度条 并适用于所有浏览器 这是基本代码
  • phpinfo 说 php.ini 路径是 C:\Windows 但那里没有 php.ini

    我们正在尝试从 PHP5 切换到 PHP7 现在我们已经安装了 Apache 并且 PHP 可以运行了 然而 我们在php ini文件没有任何作用 Via phpinfo 我们意识到原因是Configuration File php ini
  • UTF-8、PHP、Win7 - 现在是否有解决方案可以使用 php 在 Win 7 上保存 UTF-8 文件名?

    更新 只是为了不让您阅读所有内容 PHP 开头 7 1 0alpha2 在 Windows 上支持 UTF 8 文件名 感谢阿纳托尔 贝尔斯基 根据 stackoverflow 上的一些链接 我找到了部分答案 https stackover
  • 合并 url 中的 2 个输入值

    我有这样的形式
  • 谷歌日历手表过期时间超过1个月怎么办?

    我将我的 CRM 系统与 Google 日历同步 为此 我要求push notifications从我的用户 Google 日历到我的系统 我已经成功创建了手表 并将过期时间设置为2030年 但是当我收到手表事件的响应时 它显示手表的过期时
  • 如何在数据列表 HTML PHP 中设置选择

    您好我想知道是否有一种方法可以在数据列表中设置选定的值 我想要这样的东西

随机推荐

  • cython代码编译和setup.py文件编写

    Cython 官方文档 https cython readthedocs io en latest 中文文档 https www bookstack cn read cython doc zh https cython apachecn o
  • visjs DataSet支持的数据类型和选择

    数据类型 DataSet 支持以下数据类型 Name Description Examples Boolean A JavaScript Boolean true false Number A JavaScript Number 32 2
  • MFC的ActiveX控件 - 1

    转自 https blog csdn net babykangaroo article details 45795079 本文是入门学习ActiveX的学习笔记 属于系统学习整个框架部分 具体细节自己写代码时再深入 学习参考书籍是 MFC
  • 找环

    文章目录 找环 1 算法分析 1 1 判断是否存在环 1 2 找出所有环上的所有点 1 3 类拓扑排序找出与度数有关的点集 gt 退化到度数为2的环 1 4 找到以s为源点的最小环 1 5 floyd找到有向图 无向图的最小环 2 模板 2
  • 神秘时代服务器信息没汉化,[聊天

    Server thread ERROR Could not load plugins Msgreplace1 0 jar in folder plugins org bukkit plugin InvalidPluginException
  • Qt界面小技巧之设置不同模块不同颜色

    文章目录 一 效果图 二 使用场景 三 使用方法及分析 3 1 步骤 3 2 分析 总结 一 效果图 下图为不同模块不同颜色的效果图 下方每一个字符都是独立的QLabel控件 模块对应的颜色码 1 rgb 170 85 255 2 rgb
  • 日志异常检测初步实践与探索

    1 背景 日志的主要目的是记录系统 包括服务和业务等 状态和重要的事件帮助定位系统的问题 日志对于理解系统状态和定位性能问题至关重要 因此 日志是在线监控和异常检测的一个重要信息源 在很多业务和服务的故障自愈过程中 日志异常检测与根因分析是
  • 人工智能3d建模算法_从2D到3D的跨越,康云全球首创“人工智能AI+3D自动化建模与展示技术”...

    康云 人工智能AI 3D自动化建模与展示技术 第八届中国创新创业大赛 广东赛区 暨第七届 珠江天使杯 科技创新创业大赛 获奖项目巡礼系列报道八 你还在使用传统的3D建模技术 传统3D建模 模型制作成本高耗时耗力 模型体积大不方便传输 传播
  • 【DirectX12】3.配置FBX_SDK

    配置FBX SDK 1 介绍 FBX格式是现在最主流的用于游戏的3D模型格式 要使用DirectX12绘制模型 当然需要先用这个库来解析模型数据 它的版权协议如下 不是开源的并且是非商用的 假设你完成了一个引擎到时候还需要联系他们讨论版权的
  • 巨头的联盟链选择

    FISCO BCOS是完全开源的联盟区块链底层技术平台 由金融区块链合作联盟 深圳 简称金链盟 成立开源工作组通力打造 开源工作组成员包括博彦科技 华为 深证通 神州数码 四方精创 腾讯 微众银行 亦笔科技和越秀金科等金链盟成员机构 代码仓
  • leetcode-每日一题2022.4.16 最大回文数乘积

    题目 力扣 思路 一个n位数的范围在10 n 1 到10 n 1之间 两个n位数的乘积的位数是2n或2n 1位 除了n 1以外 最大回文整数的位数都是2n位 从大到小枚举每一个可能的回文整数 判断它是否能用两个n位数的乘积来表示 回文整数可
  • ESP32开发-HTTP POST请求发送图片

    HTTP POST请求发送图片 ESP32中有HTTP相关的请求demo 但是demo中只是简单的HTTP header加上body 如果服务器对POST请求有要求 比如数据以key value的形式传输 那么服务器会无法正常处理请求 从而
  • 在 Linux 系统中查找 MAC 地址的方法

    参考文章 多种方法在Linux上找到MAC地址 引言 MAC Media Access Control 地址是网络设备 如网卡 的唯一标识符 用于在局域网中进行通信 在 Linux 系统中 有几种方法可以查找设备的 MAC 地址 在本文中
  • 线性代数(六)——二次型

    文章目录 前言 二次型是什么 二次型的表示 合同矩阵与合同二次型 正定二次型 正定矩阵 二次型的题型 前言 一直对二次型和线性代数的关系不解 导致一系列的知识点因为没有理解而常常忘记 在这里对二次型进行梳理 希望可以加深对二次型的印象 二次
  • 【软件测试】POST请求包含哪些参数

    POST请求包含哪些参数 HTTP 协议是以 ASCII 码传输 建立在 TCP IP 协议之上的应用层规范 规范把 HTTP 请求分为三个部分 请求行 状态行 URL 请求头 Headers 请求体 消息主体 Body 协议规定 POST
  • 容器编排学习(一)容器技术

    一 容器 1 Linux 容器的起源 容器的起源可以追溯到1979年 UNIX 系统中提供的chroot命令 容器的最初的设计目标是为了隔离计算机中的各类资源以便降低软件开发 测试阶段的风险 或者充当蜜罐 吸引黑客的攻击 以便监视黑客的行为
  • 计算机组成原理笔记

    CPU的功能和结构 运算器 对数据进行加工 算术逻辑单元ALU 暂存寄存器 通用寄存器 累加寄存器ACC 程序状态字寄存器PSW 移位器 计数器 控制器 取指令 分析指令 执行指令 中断处理 程序计数器PC 指令寄存器IR 指令译码器 时序
  • 第53步 深度学习图像识别:Bottleneck Transformer建模(Pytorch)

    基于WIN10的64位系统演示 一 写在前面 1 Bottleneck Transformer Bottleneck Transformer 简称 BotNet 是一种深度学习模型 在2021年由Google的研究人员在论文 Bottlen
  • 【Mysql】数据库第三讲(表的约束、基本查询语句)

    表的约束和基本查询 1 表的约束 1 1 空属性 1 2默认值 1 3列描述 1 4 zerofill 1 5主键 1 6 自增长 1 7 唯一键 1 8外键 1 表的约束 真正约束字段的是数据类型 但是数据类型约束很单一 需要有一些额外的
  • 腾讯应用宝米大师直购模式支付流程以及服务端php回调校验

    一 米大师简介 1 米大师 Midas 为腾讯官方唯一虚拟支付平台 2 YSDK已经内置了米大师 Midas 支付模块 游戏开发者接入YSDK后 可以通过相应的配置开启米大师的支付功能 并调用YSDK已经封装好的接口 即可快速实现支付能力