- 下载微信JSAPI支付的 SDK : https://pay.weixin.qq.com/wiki/doc/api/download/WxpayAPI_php.zip ;解压后放在extend 文件夹下,命名为wepay
- 下载你的商户证书,放在extend/wepay/cert/ 文件夹下面。自行将 extend/wepay/example/WxPay.Config.php 的appId , mch_id, key(商户支付秘钥),appsecret ,证书路径 设置好。
- 创建新的验证控制器WechatPayNotify.php,复制下面代码进去,在最后的TODO3 那里,可以插入你在订单支付后的相关代码。比如数据库订单状态更新
use thinkfacadeCache;
require_once "../extend/wepay/lib/WxPay.Api.php";
require_once "../extend/wepay/lib/WxPay.Exception.php";
require_once "../extend/wepay/lib/WxPay.Config.Interface.php";
require_once "../extend/wepay/lib/WxPay.Data.php";
require_once "../extend/wepay/example/WxPay.JsApiPay.php";
require_once "../extend/wepay/example/WxPay.NativePay.php";
require_once '../extend/wepay/lib/WxPay.Notify.php';
require_once "../extend/wepay/example/WxPay.Config.php";class WechatPayNotify extends WxPayNotify
{public function index(){$config = new WxPayConfig();$this->Handle($config, false);}//查询订单public function Queryorder($transaction_id,$data=[]){$input = new WxPayOrderQuery();$input->SetTransaction_id($transaction_id);$config = new WxPayConfig();$result = WxPayApi::orderQuery($config, $input,$data);if(array_key_exists("return_code", $result)&& array_key_exists("result_code", $result)&& $result["return_code"] == "SUCCESS"&& $result["result_code"] == "SUCCESS"){return true;}return false;}/**** 回包前的回调方法* 业务可以继承该方法,打印日志方便定位* @param string $xmlData 返回的xml参数***/public function LogAfterProcess($xmlData){
// Log::DEBUG("call back, return xml:" . $xmlData);return;}//重写回调处理函数/*** @param WxPayNotifyResults $data 回调解释出的参数* @param WxPayConfigInterface $config* @param string $msg 如果回调处理失败,可以将错误信息输出到该方法* @return true回调出来完成不需要继续回调,false回调处理未完成需要继续回调*/public function NotifyProcess($objData, $config, &$msg){$data = $objData->GetValues();//TODO 1、进行参数校验if(!array_key_exists("return_code", $data)||(array_key_exists("return_code", $data) && $data['return_code'] != "SUCCESS")) {//TODO失败,不是支付成功的通知//如果有需要可以做失败时候的一些清理处理,并且做一些监控$msg = "异常异常";Cache::set('wx_pay_error_msg',$msg,3600);return false;}if(!array_key_exists("transaction_id", $data)){$msg = "输入参数不正确";Cache::set('wx_pay_error_msg',$msg,3600);return false;}//TODO 2、进行签名验证try {$checkResult = $objData->CheckSign($config);if($checkResult == false){Cache::set('wx_pay_error_msg','签名错误',3600);//签名错误
// Log::ERROR("签名错误...");return false;}} catch(Exception $e) {
// Log::ERROR(json_encode($e));}//查询订单,判断订单真实性if(!$this->Queryorder($data["transaction_id"],$data)){$msg = "订单查询失败";Cache::set('wx_pay_error_msg','订单错误',3600);return false;}//TODO 3、处理业务逻辑//这里是支付后的操作处理return true;}}
- 后台获取小程序几个支付参数的具体代码:
public function get_data(){//获取支付参数require_once "../extend/wepay/lib/WxPay.Api.php";require_once "../extend/wepay/lib/WxPay.Exception.php";require_once "../extend/wepay/lib/WxPay.Config.Interface.php";require_once "../extend/wepay/lib/WxPay.Data.php";require_once "../extend/wepay/example/WxPay.JsApiPay.php";require_once "../extend/wepay/example/WxPay.NativePay.php";require_once '../extend/wepay/lib/WxPay.Notify.php';require_once "../extend/wepay/example/WxPay.Config.php";$nodify_url = url('WechatPayNotify/index','','',true);//跳转到你的验证地址//①、获取用户openid$tools = new JsApiPay();$openId = input('open_id');//小程序的用户openId$out_trade_no = input('oid');//你的订单号$price = 0.01;$account = $price*100;//订单价格*100 ,单位:分try{//②、统一下单$input = new WxPayUnifiedOrder();$input->SetBody('testbox');//商品描述$input->SetAttach('testdev');//附加数据参数$input->SetSignType("MD5");//设置签名加密方式$input->SetOut_trade_no($out_trade_no);$input->SetTotal_fee($account);//订单金额,单位:分$input->SetTime_start(date("YmdHis"));$input->SetTime_expire(date("YmdHis", time() + 600));
// $input->SetGoods_tag("test");$input->SetNotify_url($nodify_url);$input->SetTrade_type("JSAPI");$input->SetOpenid($openId);$config = new WxPayConfig();$order = WxPayApi::unifiedOrder($config, $input);$temp = $order;
// print_r($temp);$key = $config->GetKey();//商户支付秘钥,不是AppSecret$app_id = $config->GetAppId();} catch(Exception $e) {
// print_r($e);$this->error('出错');}//小程序二次签名获取,MD5加密方式$timeStamp = ''.time().'';$nonceStr = $temp["nonce_str"];// 随机字符串,32位以内,随意$package = "prepay_id=".$temp["prepay_id"];//统一下单的prepay_id,格式是prepay_id = ....$string = "appId=".$app_id."&nonceStr=".$nonceStr."&package=".$package."&signType=MD5&timeStamp=".$timeStamp."&key=".$key;// 参数排序就是字典序,严格注意大小写$paySign = strtoupper(md5($string));$assign = ['error' => 0,'openid' => $openId,'appId' => $app_id,'timeStamp' => $timeStamp,'nonceStr' => $nonceStr,'package' => $temp["prepay_id"],'paySign' => (string)$paySign,];return json_encode($assign);}
至此,微信小程序支付参数获取完成。只需要在前端调用参数接口即可。
易出错的几个地方:
1. 统一下单 和 小程序二次签名使用的appId 都是小程序的appId
2. 签名方式:统一下单和 小程序二次签名使用的签名方式,保持一致。这里我用的是MD5
3.请确保商户支付秘钥的正确性,这里的key 是商户支付秘钥,不是appsecret
4.签名验证格式:请注意参数大小写,严格按照上方例子的格式来:
$string = "appId=".$app_id."&nonceStr=".$nonceStr."&package=".$package."&signType=MD5&timeStamp=".$timeStamp."&key=".$key;
可以使用签名验证工具验证:
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
5.如果上方步骤全部正确,但仍报“支付验证签名失败”,请检查你的前端格式,先把参数接口获取到的数据用var 定义,再放到支付请求接口。(这个巨坑)
6.若提示“缺乏total_fee”,请检查你的参数接口。