微信支付和微信支付通知基於sdk的說明(2)

前期準備工做

微信商戶帳戶/密碼(獲取appid等信息)
微信公衆號帳戶/密碼(獲取cert證書等信息,不作線上退款不須要證書)php

下載php支付demo

從商戶平臺進入的話是如下界面或者直接搜索公衆號支付文檔java

支付類型

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1
數據庫

 
payType.png

 

php-demo下載

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
json

 
php-demo.png

 

修改部分文件並預覽index.php

解壓文件,打開index.php修改
能夠改爲絕對路徑,即你放的位置(某個域名或者某個域名下某個文件夾下)或者相對路徑api

http://'.$_SERVER['HTTP_HOST'].'/WxpayAPI/example/jsapi.php 
 
path.png
更改配置(整個demo最重要的修改的地方)
 
config.png

說明
appId:是你的微信公衆平臺的appId
appsecret:是你商戶平臺的appsecret這兩個參數可登陸你的微信公衆平臺查看
mchId:是你的商戶Id,這個是你的微信公衆號開通微信支付,微信分配給你的一個商戶支付ID,可登錄商戶平臺查看,便是你登陸商戶平臺的帳號
key:是你商戶平臺的支付祕鑰,這個參數很關鍵,它是一個32位的字符串安全

必定要保證你以上四個參數的正確,否則出現的各類錯誤皆多是這四個參數不正確形成的,固然前提是你開通微信支付而且配置正確的受權域名和支付目錄bash

修改異步通知地址

打開example文件夾下的jsapi.php微信

$input->SetNotify_url("http://www.xxx.com/WxpayAPI/example/notify.php"); //設置接收微信支付異步通知回調地址 

改成你本身的地址,能夠寫死或者相對路徑獲取該地址網絡

添加異步通知地址配置

Wxpay.api.php中的unifiedOrder下單方法中須要session

//異步通知url未設置,則使用配置文件中的url

if(!$inputObj->IsNotify_urlSet()){ $inputObj->SetNotify_url(WxPayConfig::NOTIFY_URL);//異步通知url } 

因此若是你沒設置,則須要去WXPay.Config.php中添加一條:

const NOTIFY_URL='https://www.xxx.com/WxpayAPI/example/notify.php'; 
配置受權域名

由於微信支付要獲取openId,它是微信支付用戶的憑證

 
auth.png
配置支付目錄
 
mchId.png
上傳整個文件夾到你寫的支付目錄下的域名下

好比你的是www.xxx.com/WxpayAPI/example/
那麼你就把你整個WxpayAPI文件夾傳到你的www.xxx.com域名目錄下
預覽index.php

 
index.png

 

確認你的商戶信息
 
pay.png
重點(坑點)

支付成功jsapi中的js就能夠根據返回的信息跳轉到支付成功的頁面,這是接收微信同步返回的處理

function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', <?php echo $jsApiParameters; ?>, //訂單參數 function (res) { alert(res.err_msg); WeixinJSBridge.log(res.err_msg); if (res.err_msg == 'get_brand_wcpay_request:ok') { window.location.href = 'http://h.yiwang.com/index.php?r=cart/finishedorder&paymentId='+<?php echo $paymentId;?>+'&orderId='+<?php echo $orderId;?>; }else if (res.err_msg == 'get_brand_wcpay_request:cancel') { alert('cancel'); } else { alert('fail'); alert(res.err_msg); } } ); } 

可是最終是否支付成功不能以這個爲準,而是notify.php接收到的異步通知爲準,這是微信異步返回的結果處理

public function NotifyProcess($data, &$msg) { Log::DEBUG("call back:" . json_encode($data)); $notfiyOutput = array(); if(!array_key_exists("transaction_id", $data)){ $msg = "輸入參數不正確"; return false; } //查詢訂單,判斷訂單真實性 if(!$this->Queryorder($data["transaction_id"])){ $msg = "訂單查詢失敗"; return false; } $this->UpdateOrderStatus();//自定義更改數據庫支付成功狀態 return true; } 

具體的更改數據庫訂單狀態須要接收到微信異步通知的xml,而後判斷是否支付成功,再進行更改

function UpdateOrderStatus() { $string = file_get_contents("php://input");//微信返回的xml支付結果 $arr = (array) simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA); if ($arr['result_code'] == 'SUCCESS' && $arr['return_code'] == 'SUCCESS') { //操做數據庫處理訂單狀態等 } } 

以上是分析的demo大體流程,接下來我說一下我遇到的坑,望各位注意:

坑一:簽名錯誤

這是我最開始調試SDK的demo時候第一個坑
咱們公司把已經使用是APP的商戶Id和key給我,讓我用這個,這個後臺能夠登陸,我看到了商戶id沒問題,但key看不到,只有重置才能夠,由於線上用着,我也無法重置,還覺得代碼有問題,各類輸出查看。
百度好多人都讓重置key,說同一個key從新提交一次也行,有人提交兩三次同一個key,說就不報簽名無效了。但咱們沒有開發環境,我不能任性重置。只能找代碼的問題

最終發現仍是第一步的四個配置參數有問題,appId沒問題是公衆號的id,我沒用他們給個人appId,他們的appId應該是App開放平臺的appId

商戶id和祕鑰,給個人是app的商戶id和key,其實不是。應該是咱們微信公衆號申請微信支付分配的商戶id和祕鑰。而不是說用APP申請的商戶id和祕鑰。
雖然文檔說的很清楚,我也知道,但領導就說和app共用一個,我也很無奈。由於開始我也不是很清楚,就以爲那就是吧,或許是demo有問題(哈哈哈)

坑二:out_trade_no的最少位數問題

微信說是32位之內,可是,若是你傳1位,確定會報錯,它的提示還很弱,不是說位數不足,具體什麼提示我忘了。反正位數太少會出錯,我在這裏也是摔了個跟頭

坑三:不知道notify.php這個文件怎麼接收微信支付返回結果

搜了好多資料,大部分人都只講解了demo,說支付成功以異步通知爲準,微信是通知給你設置的地址了,但問題是我怎麼獲取他的通知呢?

老是以爲沒有返回變量,就不知道怎麼輸出變量,怎麼處理。

$string = file_get_contents("php://input"); 

這就是接收到微信的通知,一個xml,詳細代碼上邊有

坑四:jsapi.php接收不到上一個頁面post或get傳過來的參數

緣由:在建立商戶訂單時,須要獲取到用戶的openid

//①、獲取用戶openid $tools = new JsApiPay(); $openId = $tools->GetOpenid(); 

Wxpay.JsApiPay.php
可是在獲取用戶openid的過程當中須要請求CODE,CODE請求函數以下:

public function GetOpenid() { //經過code得到openid if (!isset($_GET['code'])){ //觸發微信返回code碼 $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING']); $url = $this->__CreateOauthUrlForCode($baseUrl); Header("Location: $url"); exit(); } else { //獲取code碼,以獲取openid $code = $_GET['code']; $openid = $this->getOpenidFromMp($code); return $openid; } } 

所以,在獲取openid商戶後臺與微信系統進行屢次交互,當再次回到生成商戶訂單頁的時候,咱們以前從h5頁面經過$_GET或者$_POST方式獲取的參數已經被清空,因此沒法生成商戶訂單。
解決辦法:
1.先將用戶h5頁面提交過來的參數保存到session中,而後再重定向到要生成商戶訂單的頁面,
在生成商戶訂單的頁面中先獲取openid,再獲取session
中的值(這是我百度到別人採用的方法)
2.個人辦法:
在獲取openid以前把post或者get的參數取到,而後傳給微信(採用和他獲取code的機制同樣)

//①、獲取用戶openid $tools = new JsApiPay(); $arr = $tools->GetOpenid($Out_trade_no,$paymentId,$Total_fee); 

重寫GetOpenid方法,以下:

public function GetOpenid($orderId,$paymentId,$totalFee) { //經過code得到openid if (!isset($_GET['code'])){ //觸發微信返回code碼 $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING'].'?orderId='.$orderId.'&paymentId='.$paymentId.'&totalFee='.$totalFee); $url = $this->__CreateOauthUrlForCode($baseUrl); Header("Location: $url"); exit(); } else { //獲取code碼,以獲取openid $code = $_GET['code']; $orderId = $_GET['orderId']; $paymentId= $_GET['paymentId']; $totalFee = $_GET['totalFee']; $openid = $this->getOpenidFromMp($code); return $arr; } } 
金額的問題

傳遞的金額,微信是以分爲單位,而通常是以元爲單位,因此記得金額轉換一下,不要傳給微信小數點
還有這個金額最好在jsapi這個頁面,查詢一下數據庫該筆訂單應支付多少,而不是從提交訂單頁面傳輸過來,這樣不安全,也別覺得請求接口會安全,都不安全,只要存在網絡傳輸就會出現篡改,最好是本身在本頁面查詢出來,而後傳給微信

out_trade_no的問題
(說明這是針對咱們的流程設計出次下策)

咱們的提交訂單會生成一個orderId和paymentId存在咱們的兩個表中(這兩個表),而後由於要給微信傳咱們本身的訂單id,通常來講只須要傳orderId就行,可是接收到微信異步通知的支付成功之後, 咱們須要根據paymenId去改咱們的支付狀態。
問題是從微信返回時咱們沒有paymentId。
用orderId去查可能會不惟一(咱們數據庫設計如此,會有多訂單支付),另外一方面是屢次請求會慢,因此我採起了把訂單id和paymentId拼接在一塊兒做爲傳給微信,而後支付成功之後微信返回out_trade_no就是咱們的orderId和paymentId

轉載:https://www.jianshu.com/p/e2f756146a0e

相關文章
相關標籤/搜索