字节跳动(头条)小程序 支付,回调处理

编程入门 行业动态 更新时间:2024-10-28 05:18:54

字节跳动(头条)小程序 支付,<a href=https://www.elefans.com/category/jswz/34/1771356.html style=回调处理"/>

字节跳动(头条)小程序 支付,回调处理

本人针对字节调动小程序的官方开发文档真的无力吐槽,文档真的简陋。而且文档有错别字。槽点有点多。

头条因为没有自己的支付渠道,所以使用的是支付宝,利用tt.requestPayment()调起支付宝APP支付:

支付具体流程为:

一、后端通过openid和自己这边的订单号生成一个头条的订单号,具体操作可以看文档流程
二、生成调用支付宝的一个字符串,这里需要使用支付宝文档,我使用的支付宝SDK,这边支付宝文档很好的,网上资料很多。
三、最后就是组装后返回给前端调用支付宝。特别注意的是这里使用的所有appid等参数都是头条分配给商户的appid等。


首先我们通过代码来实现字节跳动小程序支付单号(trade_no)的生成。我这里用的是PHP代码,通过文档,对参数进行处理。

//这里是真的回调地址进行的简单处理
$http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';
$website                = $http_type . $_SERVER['HTTP_HOST'];$risk_info              = $this->getRealIp();    //获取用户真实IP(我在这里写了一个获取IP的方法)
$payload['app_id']      = $tt_pay_app_id;  		 //头条支付分配给业务方的ID(不是头条小程序的appid)
$app_secret             = $tt_pay_secret_key;  	 //头条支付分配给业务方的支付秘钥
$payload['charset']     = "utf-8";               // 请求使用的编码格式
$payload['method']      = "tp.trade.create";  	 // 接口名称
$payload['timestamp']   = time();           	 // 发送请求的时间
$biz_content            = ["out_order_no" => $data['out_trade_no'],    	//商户订单号"uid"          => $data['openid'],    			//唯一标识用户open_id"merchant_id"  => $tt_merchant_id,    			//头条支付分配给业务方的商户号"total_amount" => $data['fee'] * 100,    		//金额,分为单位,应传整型"currency"     => "CNY", 						//币种"subject"      => $data['subject'],    			//商户订单名称"body"         => $data['body'],    			//商户订单详情"trade_time"   => time(),    					//下单时间戳"valid_time"   => "60",    						//订单有效时间     单位:秒"notify_url"   => $website . '/payment/toutiao/notify.php',    //服务器异步通知http地址"risk_info"    => json_encode(['ip' => $risk_info]),    	   //用户的真实ip
]; // 请求参数的集合   json
$payload['biz_content'] = json_encode($biz_content);
$payload['sign_type']   = "MD5";		//头条采用的是MD5加密
$payload['format']      = "json";
$payload['version']     = "1.0";
$stringToBeSigned = $this->getSignContent($payload , $payload['charset'] , $app_secret);	//这里写了一个签名的方法
$payload["sign"]  = md5($stringToBeSigned);$url        = ""; // 请求地址正式环境
$result     = ihttp_post($url, $payload);
$result     = json_decode($result['content'], true);
$resultCode = $result['response']['code'];
if (!empty($resultCode) && $resultCode == 10000) {//后面会针对这一块进行处理//这里需要拼装参数请求支付宝APP支付return ['error'=>0 , 'msg'=>'success' , 'res'=>$result];
} else {return ['error'=>-1 , 'msg'=>'failed' , 'res'=>$result];
}

当我们点击点单支付按钮的时候,将所需要的参数传至以上接口方法中进行处理,能够正常返回头条的trade_no。
返回结果如下:

接下来就是上述方法中的两个方法的调用,一个使用户IP地址的获取,一个是头条签名的处理方法。重点是后面一个。
先看用户IP地址的获取方法,如下:

/*** 获取用户真实IP* @return bool*/
public function getRealIp() {$ip = false;if (!empty($_SERVER["HTTP_CLIENT_IP"])) {$ip = $_SERVER["HTTP_CLIENT_IP"];}if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {$ips = explode(", ", $_SERVER['HTTP_X_FORWARDED_FOR']);if ($ip) {array_unshift($ips, $ip);$ip = FALSE;}for ($i = 0; $i < count($ips); $i++) {if (!eregi("^(10│172.16│192.168).", $ips[$i])) {$ip = $ips[$i];break;}}}return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}

该方法不做过多描述,接下来是重点。

通过文档可以看出,我们要先对请求参数去除空值和不参与签名的字段,然后进行排序。代码如下:

/*** 签名处理* @param $params* @param $charset* @return string*/public function getSignContent($params , $charset,$app_secret) {ksort($params);$stringToBeSigned = "";$i = 0;foreach ($params as $k => $v) {if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {// 转换成目标字符集$v = $this->characet($v, $charset);if ($i == 0) {$stringToBeSigned .= "$k" . "=" . "$v";} else {$stringToBeSigned .= "&" . "$k" . "=" . "$v";}$i++;}}$stringToBeSigned = $stringToBeSigned.$app_secret;unset ($k, $v);return $stringToBeSigned;}/*** 校验$value是否非空* @param $value* @return  boolean;*  if not set ,return true;*  if is null , return true;**/public function checkEmpty($value) {if (!isset($value))return true;if ($value === null)return true;if (trim($value) === "")return true;return false;}/*** 转换字符集编码* @param $data* @param $targetCharset* @return string*/public function characet($data, $targetCharset) {if (!empty($data)) {$fileType = "UTF-8";if (strcasecmp($fileType, $targetCharset) != 0) {$data = mb_convert_encoding($data, $targetCharset, $fileType);}}return $data;}

通过以上方法我们已经能够获取到正常的响应数据了。就像这样

{"response":{"code":"10000","msg":"Success","trade_no":"1004130000127421"},"sign":"ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}

但是,接下来问题来了。我们需要再次的拼装参数,去请求支付宝APP支付。然后将数据返回给前端,通过前端拉起支付宝收银台。
但是这一块,官方文档写的很… … 以至于,本小白看的是一脸懵。

我在正确获取trade_no订单号的时候,做了以下处理:
关于这一块的参数,可以参考文档:.html

//在这里是要将数据返回给前端,通过前端拉起支付宝收银台$data2                 = [];
$data2['trade_no']     = $result['response']['trade_no'];	//刚刚获取到的trade_no订单号
$data2['app_id']       = $payload['app_id'];				//头条支付分配给业务方的ID
$data2['sign_type']    = $payload['sign_type'];				//头条采用的MD5
$data2['timestamp']    = $payload['timestamp'];				//发送请求的时间
$data2['merchant_id']  = $biz_content['merchant_id'];		//头条支付分配给业务方的商户号
$data2['uid']          = $biz_content['uid'];				//唯一标识用户open_id(这个是头条的)
$data2['total_amount'] = $biz_content['total_amount'];		//金额,分为单位,应传整型
$data2['params']       = json_encode(['url' => $this->aliapppaytest($data , $biz_content , $data2 , $website , $config)]);		//这里是支付宝APP支付的请求参数,我在这里使用了支付宝的SDK$stringToBeSigned      = $this->getSignContent($data2, $payload['charset'], $app_secret);	//将以上参数再次进行签名处理
$data2["sign"]         = md5($stringToBeSigned);$data2['pay_channel']  = "ALIPAY_NO_SIGN";
$data2["pay_type"]     = "ALIPAY_APP";
$data2['method']       = 'tp.trade.confirm';
$data2['risk_info']    = $biz_content['risk_info'];
return ['error'=>0 , 'msg'=>'success' , 'res'=>$data2];			// 将这些参数,返回给前端处理就可以了

主要是参数params中的url处理

这里使用了支付宝的SDK,如下:

public function aliapppaytest($data , $biz_content , $data2 , $website , $config){require  dirname(__FILE__) .'/../library/alipay/AopSdk.php';$aop                     = new \AopClient();$aop->gatewayUrl         = ".do";$aop->appId              = $config['ali_app_app_id'];                //支付宝APPID$aop->rsaPrivateKey      = $config['ali_app_rsa_pri_key'];        //支付宝秘钥$aop->format             = "json";$aop->charset            = "UTF-8";$aop->signType           = "RSA2";$aop->alipayrsaPublicKey = $config['ali_app_pay_rsa_pub_key'];   //支付宝公钥//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay$request = new AlipayTradeAppPayRequest();  //SDK已经封装掉了公共参数,这里只需要传入业务参数$data2 = ['body'            => $data['body'],'subject'         => $data['subject'],'out_trade_no'    => $data2['trade_no'],'timeout_express' => '30m','total_amount'    => $data['fee'],'product_code'    => 'QUICK_MSECURITY_PAY',];$postdata = json_encode($data2);$request->setNotifyUrl($website . '/payment/toutiao/notify.php');    //服务器异步通知http地址);$request->setBizContent($postdata);$response = $aop->sdkExecute($request);     //这里和普通的接口调用不同,使用的是sdkExecute//htmlspecialchars是为了输出到页面时防止被浏览器将关键参数html转义,实际打印到日志以及http传输不会有这个问题
//        return htmlspecialchars($str);//就是orderString 可以直接给客户端请求,无需再做处理。return $response;//就是orderString 可以直接给客户端请求,无需再做处理。}

到这里,整个支付阶段就已经结束了。此时,前端拉起支付宝收银台进行付款,支付成功之后,关于回调的处理,其实就是支付宝本身的回调处理了。直接$_POST接收数据,通过支付宝验签处理就可以了。详情,参考PHP 支付宝小程序 支付以及回调处理

关于唤起支付页面报错的问题,请参考支付宝APP支付:
ALI40247-自查方案:.php?tid=250&fid=60
ALI38173-排查方案:.php?tid=3546&fid=60
ALIN10146-自查方案:.php?tid=6918&fid=60

以上欢迎各位指点。

更多推荐

字节跳动(头条)小程序 支付,回调处理

本文发布于:2024-03-08 20:46:34,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1722281.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:回调   字节   头条   程序

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!