2020-02-10 18:02:13
围观(5438)
去年写过一篇文章:PHP开发微信支付功能
但是那篇文章用的是 NATIVE 支付方式,就是扫码支付,请求微信后返回的是一段 weixin:// 协议的链接,然后手机扫码调起微信支付.
其实微信小程序支付也差不多,只是支付方式用的是 JSAPI ,区别就是小程序支付 比 扫码支付 多了个openid的参数.
直接上代码:
public function pay()
{
// 支付数据
$data['out_trade_no'] = '这里需要生成订单号 可用 md5 函数生成当前时间 + 随机数 比如 md5(time . rand(100, 999))';
// 当然还有很多其他生成订单号的方法 博主仅仅是举例
$data['total_fee'] = 100; // 这个就是支付金额 此金额单位为分 比如 100 调起支付后是支付 1 分钱
$data['spbill_create_ip'] = $_SERVER["REMOTE_ADDR"]; // 客服端的 IP 可以使用其他方式获取,本文仅演示
$data['attach'] = '附加数据,在查询API和支付通知中原样返回';
$data['body'] = '产品名称 在支付的时候显示的';
$data['appid'] = '公众号的 APPID';
$data['mch_id'] = '微信支付的商户号';
$data['nonce_str'] = md5(time() . rand(0, 999)); // 这个是随机字串 具体看官方文档吧
$data['trade_type'] = 'JSAPI'; // 支付方式 扫码用 NATIVE 小程序用 JSAPI 也是本文的内容.
$data['openid'] = '用户的openid 比如是A用户调用充值功能 就需要传A用户的openid 谁支付就用谁的';
// 异步回调地址 回调地址就不多说了...
$data['notify_url'] = ($_SERVER['HTTPS'] ?? 'http' == 'on' ? "https://" : "http://") . $_SERVER["HTTP_HOST"] . '/api/wechat_callback';
// 将参数签名
$sign = $this->get_param($data);
$data_xml = "<xml>
<appid>".$data['appid']."</appid>
<attach>".$data['attach']."</attach>
<body>".$data['body']."</body>
<mch_id>".$data['mch_id']."</mch_id>
<nonce_str>".$data['nonce_str']."</nonce_str>
<notify_url>".$data['notify_url']."</notify_url>
<openid>".$data['openid']."</openid>
<out_trade_no>".$data['out_trade_no']."</out_trade_no>
<spbill_create_ip>".$data['spbill_create_ip']."</spbill_create_ip>
<total_fee>".$data['total_fee']."</total_fee>
<trade_type>".$data['trade_type']."</trade_type>
<sign>".$sign."</sign>
</xml>";
// 微信统一下单接口地址
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
// 发起HTTP请求 因为用的是 Laravel 框架,所以可以使用 GuzzleHttp 类
// 如果报错 Guzzle\Http 不存在,可以装一下 GuzzleHttp 包.
$http = new GuzzleHttpClient;
$response = $http->request('POST', $url, ['body' => $data_xml]);
$wechat_pay_res = $this->xml_to_array($response->getBody());
if($wechat_pay_res['return_code'] !== 'SUCCESS' && $wechat_pay_res['return_msg'] !== 'OK') {
// 开启数据库事务 在这里需要抛出异常 回滚数据
// 微信支付请求失败了
}
// 需要给前端那边 小程序用到的数据
$mini_program_pay_params['appId'] = $gzh_config['appid'];
$mini_program_pay_params['timeStamp'] = time();
$mini_program_pay_params['nonceStr'] = $data['nonce_str'];
$mini_program_pay_params['package'] = 'prepay_id=' . $wechat_pay_res['prepay_id'];
$mini_program_pay_params['signType'] = 'MD5';
$sign = $this->get_param($mini_program_pay_params);
$mini_program_pay_params['paySign'] = $sign;
$mini_program_pay_params['prepay_id'] = $wechat_pay_res['prepay_id'];
$mini_program_pay_params['out_trade_no'] = $data['out_trade_no'];
$mini_program_pay_params['total_fee'] = $data['total_fee'];
return $mini_program_pay_params;
// 可以这样传
// return response()->json(['mini_program_pay_params' => $mini_program_pay_params]);
}
private function get_param($param_array, $isencode = false)
{
$paramStr = '';
ksort($param_array);
$i = 0;
foreach($param_array as $key => $value){
if ($key == 'Signature'){
continue;
}
if ($i == 0){
$paramStr .= '';
}else{
$paramStr .= '&';
}
$paramStr .= $key . '=' . ($isencode ? urlencode($value) : $value);
++$i;
}
$api_key = '微信支付密钥';
$stringSignTemp = $paramStr."&key={$api_key}";
return strtoupper(md5($stringSignTemp));
}
private function xml_to_array($xml)
{
libxml_disable_entity_loader(true);
$xml_string = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
return json_decode(json_encode($xml_string), true);
}这样就完成了后端请求微信接口,拿到提供给前端那边调起支付的参数了.
前端开发调起小程序支付看这个文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=5
示例代码:
wx.requestPayment({
'timeStamp': '',
'nonceStr': '',
'package': '',
'signType': 'MD5',
'paySign': '',
'success':function(res){},
'fail':function(res){},
'complete':function(res){}
})还有就是后端的异步回调,拿微信支付结果通知的,看博主之前发布的那篇文章就好了:PHP开发微信支付功能
本文地址 : bubaijun.com/page.php?id=164
版权声明 : 未经允许禁止转载!
上一篇文章: PHP使用地址获取附近小区信息
下一篇文章: PHP使用经纬度获取两个位置的距离及范围查询