这里感谢链接,基于此代码写出此文章
微信小程序B2B支付 php版_微信b2b支付-CSDN博客
相关微信文档(文档相当相当不完善!至少对于我这样的菜鸡来说、先要仔细看一遍微信文档)
微信小程序需要准备的:
1.开通BtoB商户号并与小程序绑定
2.小程序端在开发管理中开启消息推送功能、开通时选择明文、JSON(消息推送类似一个支付回调地址,在支付或退款完成之后微信服务器会给到推送事件、可以在接收推送事件时进行业务流程,要先写好一个能访问的接口)
3.在门店BtoB助手支付管理中获取 沙箱AppKey和现网AppKey
(注)需获取用户session_key,每次登录时获取session_key要记录下来,每次登录session_key会变化
获取支付参数(注意用户的session_key、注意env和appkey匹配)
public function payB()
{
$appkey = ''; //appKey、在小程序页面获取
$session_key = $this->user['session_key'];
$signData = [];
$signData['mchid'] = 'xxxxxxxxxxx'; //商户号
$signData['out_trade_no'] = 'xxxxxxxxxxxxxxxxxxxx';
$signData['description'] = 'XXXXXXXX';
$signData['amount'] = [
'order_amount' => intval($order->pay_price * 100),
'currency' => 'CNY'
];
$signData['env'] = 0;
$postdata = json_encode($signData,256);
$paySign = $this->calc_pay_sig('requestCommonPayment',$postdata,$appkey);
$signature = $this->calc_signature($postdata,$session_key);
return $this->renderSuccess('', [
'signData' => $postdata,
'mode' => 'retail_pay_goods',
'paySig' => $paySign,
'signature' => $signature,
]);
}
//签名算法
public function calc_pay_sig($uri, $post_body, $appkey)
{
$temp = $uri . '&' . $post_body;
return hash_hmac('sha256', $temp, $appkey);
}
//用户登录态signature签名算法
public function calc_signature($post_body, $session_key)
{
return hash_hmac('sha256', $post_body, $session_key);
}
接收后端参数,uniapp前端调起
wx.requestCommonPayment({
signData: result.data.signData,
mode: result.data.mode,
paySig: result.data.paySig,
signature: result.data.signature,
success: res => {
// console.log(22222222);
paySuccess(result, self, success);
},
fail: res => {
console.log(res.errMsg);
console.log(3334445689,res);
self.showError('订单未支付成功', () => {
payError(result, fail);
});
},
});
支付成功或退款成功后的信息通知
//采用的明文模式(密文的获取到数据需要先进行解密) json格式数据推送
public function actionWx_msg_notify()
{
$signature = empty($_GET["signature"]) ? '' : $_GET["signature"];
$timestamp = empty($_GET["timestamp"]) ? '' : $_GET["timestamp"];
$nonce = empty($_GET["nonce"]) ? '' : $_GET["nonce"];
$echostr = empty($_GET["echostr"]) ? '' : $_GET["echostr"];
$token = "AAA";
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature && $echostr){
echo $echostr;
exit;
} else {
$input = file_get_contents("php://input");
$data = json_decode($input,true);
$Event = $data['Event'] ?? '';
switch ($Event) {
case 'retail_pay_notify'://b2b订单支付回调
// 订单状态,枚举值
// ORDER_INIT:订单初始化
// ORDER_PRE_PAY:订单预下单成功,待支付
// ORDER_PAY_SUCC:订单支付成功
// ORDER_CLOSE:订单已关闭
// ORDER_REFUND_PROCESSING:订单正在退款中
// ORDER_REFUND:订单已有退款
$pay_status = $data['pay_status'] ?? '';//订单状态
if ($pay_status == 'ORDER_PAY_SUCC') {
//订单支付成功
$pay_time = $data['pay_time'];//支付时间
$out_trade_no = $data['out_trade_no'];//商户订单号
$pay_amount = round($data['amount']['pay_amount'] / 100,2);//支付金额
$transactionid = $data['wxpay_transaction_id'];//微信支付订单号
//Todo 业务处理
//
echo 'success';
exit;
}
break;
case 'retail_refund_notify':
$refund_status = $data['refund_status'] ?? '';
if($refund_status == 'REFUND_SUCC') {
//Todo 业务处理
$out_trade_no = $data['out_trade_no'];
echo 'success';
exit;
}
break;
}
}
}
退款及查询订单(注:退款需要订单状态为完成,我的经验是在支付3分钟后微信订单会转为完成,这里需要先查询微信端订单状态再退款)
坑1:退款appkey必须使用现网
坑2:退款 订单号或者小程序订单号必须传其中一个!
//查询微信端订单状态
$signData['mchid'] = 'xxxxxxxxxx';
$signData['out_trade_no'] = 'xxxxxxxxxxxxxxx';
$postdata = json_encode($signData,256);
$appkey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$uri = '/retail/B2b/getorder';
$pay_sig = $this->calc_pay_sig($uri, $postdata, $appkey);
$accessToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$apiUrl = "https://api.weixin.qq.com/retail/B2b/getorder?access_token=$token&pay_sig=$pay_sig";
// $params = json_encode($post_data, JSON_UNESCAPED_UNICODE);
// 执行请求, 256
$result = json_decode($this->post($apiUrl, $postdata),true);
//退款
$post_data = [
'mchid' => 'xxx',
'out_trade_no' => xxxxxxxxxx,
'out_refund_no' => xxxxxxxxxxx,
'refund_amount' => 200,
'refund_from' => 2
];
$appkey = 'xxxxxxxxxxxxxxxxxxxxxxxx';
$post_body = json_encode($post_data, 256);
$pay_sig = $this->calc_pay_sig('/retail/B2b/refund', $post_body, $appkey);
$apiUrl = "https://api.weixin.qq.com/retail/B2b/refund?access_token=$token&pay_sig=$pay_sig";
// $params = json_encode($post_data, JSON_UNESCAPED_UNICODE);
// 执行请求
$result = $this->post($apiUrl, $post_body);
// 返回结果
$response = json_decode($result, true);
//curl请求
protected function post($url, $data = [], $useCert = false, $sslCert = [])
{
$header = [
'Content-type: application/json;'
];
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
if ($useCert == true) {
// 设置证书:cert 与 key 分别属于两个.pem文件
curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($curl, CURLOPT_SSLCERT, $sslCert['certPem']);
curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($curl, CURLOPT_SSLKEY, $sslCert['keyPem']);
}
$result = curl_exec($curl);
curl_close($curl);
return $result;
}