
- 下載微信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”,請檢查你的參數接口。