香水电影完整版在线观看未删减|久草在线国产|欧美伊人电影|美女福利视频在线,大开色戒完整版迅雷,久艹久,动画片大尺度未删减电影

軟件開發(fā),網(wǎng)站建設(shè),微信小程序制作,抖音小程序開發(fā)

點(diǎn)

動(dòng)

態(tài)

業(yè)

軟件開發(fā),網(wǎng)站建設(shè),微信小程序制作,抖音小程序開發(fā)
微信小程序、ThinkPHP5 集成微信支付過程
發(fā)布時(shí)間:2024-12-09  閱讀量:361

在微信小程序項(xiàng)目中,需要接入微信支付,用戶在小程序中點(diǎn)擊【付款】,喚起微信支付的彈窗,輸入密碼進(jìn)行支付,雖然支付流程很簡單,但真正接入的時(shí)候難免會(huì)遇到一些問題。

項(xiàng)目環(huán)境

客戶端:微信小程序
服務(wù)器:CentOS 7、PHP 7.0、Nginx、MySQL 5.6
后臺(tái)框架:ThinkPHP 5

準(zhǔn)備工作

  1. 申請(qǐng)微信小程序賬號(hào),并完成微信支付的事情工作。這些工作按照微信的要求一步步進(jìn)行即可。
  2. 配置項(xiàng)目環(huán)境,需要注意的是接口的請(qǐng)求地址需要是https,可以到阿里云申請(qǐng)一年免費(fèi)的SSL證書,按照Nginx的配置完成。
  3. 在微信小程序后臺(tái)管理上完成微信支付的申請(qǐng)之后,就可以使用微信郵件給你的賬號(hào)密碼登陸商戶平臺(tái)https://pay.weixin.qq.com。
  4. 在商戶平臺(tái)的【賬戶中心】->【API安全】中下載證書,以及【設(shè)置API密鑰】,這兩部分在代碼配置中需要。
  5. 下載SDK地址。將lib目錄下的文件拷貝到項(xiàng)目的extend下的wxpay目錄中。
  6. 配置extend/wxpay/WxPay.Config.php,將其中的參數(shù)和上面下載的證書路徑配置好。

微信支付參考文檔:開發(fā)文檔

微信小程序文檔:開發(fā)文檔

具體開發(fā)

創(chuàng)建一個(gè)訂單

這一步很簡單,就是常規(guī)的根據(jù)用戶購買信息創(chuàng)建訂單,將數(shù)據(jù)保存到數(shù)據(jù)庫。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 創(chuàng)建訂單
*
* @return void
*/

public function create()
 {

   $order = new OrderModel();
   $order['title'] = $title.'-'.date('Ymd');
   $order['out_trade_no'] = WxPayConfig::MCHID.time();
   $order['amount'] = $amount;
   $order['status'] = 0;
   if ($order->save()) {
       return json_encode(['error' => 0, 'msg' => '創(chuàng)建成功']);
   }
   return json_encode(['error' => 1026, 'msg' => '創(chuàng)建失敗']);
}


喚起支付窗口

在小程序中發(fā)起微信支付請(qǐng)求很簡單,需要注意的是,在調(diào)用wx.requestPayment({})前需要獲取簽名數(shù)據(jù),如以下的代碼所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
app.requestData('Wxpay/sign', { id: id, openid: openid }, 'GET', function (res) {
 if (res.error) {
   app.showToast(res.msg, 'success', 2000)
 } else {
   wx.requestPayment({
     timeStamp: res.result.timeStamp,
     nonceStr: res.result.nonceStr,
     package: res.result.package,
     signType: res.result.signType,
     paySign: res.result.paySign,
     'success': function (res) { },
     'fail': function (res) { },
     'complete': function (res) { }
   })
 }
}, function (res) {
 app.showToast(res.errMsg, 'success', 2000)
})


獲取支付簽名參數(shù)

在上一步的請(qǐng)求之前,需要獲取簽名參數(shù),需要注意的是獲取簽名參數(shù)是需要當(dāng)前微信用戶的openid的(id是訂單的id),先忽略openid如何獲取,看簽名方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?php
 
namespace appapicontroller;
 
use thinkLoader;
 
use appapicontrollerBase;
 
use appcommonmodelOrder as OrderModel;
 
Loader::import('wxpay/WxPay', EXTEND_PATH, '.Api.php');

class Wxpay extends Base
{

   public $data = null;
   private $curl_timeout = 3000;

   /**
    * 獲取支付參數(shù)
    *
    * @return void
    */

   public function sign()
   {

       $id = input('?get.id') ? trim(input('get.id')) : 0;
       $openid = input('?get.openid') ? trim(input('get.openid')) : 0;
       if (!$openid) {
           return json_encode(['error' => 4001, 'msg' => '用戶參數(shù)錯(cuò)誤']);
       }
       $order = OrderModel::get($id);
       if (!$order) {
           return json_encode(['error' => 4002, 'msg' => '訂單不存在']);
       }
       // 統(tǒng)一下單
       $input = new WxPayUnifiedOrder();
       $input->SetBody($order->title);
       $input->SetAttach($order->id);
       $input->SetOut_trade_no($order->out_trade_no);
       $input->SetTotal_fee(floatval($order->amount) * 100);  // 單位為分
       $input->SetTime_start(date("YmdHis"));
       $input->SetTime_expire(date("YmdHis", time() + 600));
       $input->SetGoods_tag("wx-app");
       $input->SetNotify_url(config('wxpay.pay_notify_url'));
       $input->SetTrade_type("JSAPI");
       $input->SetOpenid($openid);
       $order = WxPayApi::unifiedOrder($input);

       $jsApiParameters = $this->GetJsApiParameters($order);
       if ($jsApiParameters) {
           return json_encode(['error' => 0, 'msg' => '支付參數(shù)', 'result' => json_decode($jsApiParameters)]);
       }
       return json_encode(['error' => 4001, 'msg' => '參數(shù)錯(cuò)誤']);
   }
}

/**
*
* 獲取jsapi支付的參數(shù)
* @param array $UnifiedOrderResult 統(tǒng)一支付接口返回的數(shù)據(jù)
* @throws WxPayException
*
* @return json數(shù)據(jù),可直接填入js函數(shù)作為參數(shù)
*/

private function GetJsApiParameters($UnifiedOrderResult)
{

   if (!array_key_exists("appid", $UnifiedOrderResult)
       || !array_key_exists("prepay_id", $UnifiedOrderResult)
       || $UnifiedOrderResult['prepay_id'] == "")
   {
       return null;
   }
   $jsapi = new WxPayJsApiPay();
   $jsapi->SetAppid($UnifiedOrderResult["appid"]);
   $timeStamp = time();
   $jsapi->SetTimeStamp("$timeStamp");
   $jsapi->SetNonceStr(WxPayApi::getNonceStr());
   $jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);
   $jsapi->SetSignType("MD5");
   $jsapi->SetPaySign($jsapi->MakeSign());
   $parameters = json_encode($jsapi->GetValues());
   return $parameters;
}


以上就是完整的獲取支付簽名參數(shù)的代碼,需要注意的notify_url,這個(gè)微信支付成功的回調(diào)地址,保證瀏覽器可以正常訪問即可。

支付回調(diào)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
* 微信支付回調(diào)
*
* @return void
*/

public function callback()
{

   $xml = file_get_contents("php://input");
   $data = WxPayResults::Init($xml);
   if (!array_key_exists("transaction_id", $data)) {
       return $this->toXML(['return_code' => 'FAIL', 'return_msg' => '參數(shù)錯(cuò)誤']);
   }
   //查詢訂單,判斷訂單真實(shí)性
   if (!$data["out_trade_no"] || !$this->Queryorder($data["transaction_id"])) {
       return $this->toXML(['return_code' => 'FAIL', 'return_msg' => '訂單真實(shí)性存疑']);
   }
   $order = OrderModel::where(['out_trade_no' => $data["out_trade_no"]])->find();
   if (!$order) {
       return $this->toXML(['return_code' => 'FAIL', 'return_msg' => '訂單不存在']);
   }

   $order->status = 1;
   if ($order->save()) {
       return $this->toXML(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
   }
   return $this->toXML(['return_code' => 'FAIL', 'return_msg' => '回調(diào)失敗']);
}

/**
* 查詢訂單
*
* @param [type] $transaction_id
* @return void
*/

private function Queryorder($transaction_id)
{

   $input = new WxPayOrderQuery();
   $input->SetTransaction_id($transaction_id);
   $result = WxPayApi::orderQuery($input);
   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;
}

/**
* array轉(zhuǎn)xml
*
* @param [type] $value
* @return void
*/

public function toXML($values)
{

   if(!is_array($values) || count($values) <= 0) {
       return "<xml></xml>";
   }

   $xml = "<xml>";
   foreach ($values as $key => $val) {
       if (is_numeric($val)) {
           $xml.="<".$key.">".$val."</".$key.">";
       }else{
           $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
       }
   }
   $xml.="</xml>";
   return $xml;
}

這里主要就是在回調(diào)方法中將訂單的狀態(tài)變換一下。

獲取用戶 openid

回到上面提到的簽名方法,在那個(gè)方法中需要提供用戶的openid,獲取的流程在小程序的開發(fā)文檔中有,其次服務(wù)器端的實(shí)現(xiàn)在下載的sdksample中也能夠找到,如以下所示:
小程序端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//調(diào)用登錄接口
wx.login({
 success: function (res) {
   if (res.code) {
     if (!wx.getStorageSync('openid')) {
       that.requestData('Wxpay/openid', {
         code: res.code
       }, 'GET', function (res) {
         if (res.error) {
           that.showToast(res.msg, 'success', 2000)
         } else {
           wx.setStorageSync('openid', res.result)
         }
       })
     }
   } else {
     that.showToast("用戶登錄失敗", 'success', 1000)
   }
 }
})


服務(wù)器端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
* 獲取用戶的 openid
*
* @return thinkResponse
*/

public function openid()
{

   $code = input('?get.code') ? trim(input('get.code')) : '';
   if (!$code) {
       return json_encode(['error' => 2001, 'msg' => '獲取用戶登錄狀態(tài)失敗']);
   }
   $openid = $this->getOpenidFromMp($code);
   return json_encode(['error' => 0, 'msg' => '獲取用戶登錄狀態(tài)成功', 'result' => $openid]);
}

/**
*
* 通過code從工作平臺(tái)獲取openid機(jī)器access_token
* @param string $code 微信跳轉(zhuǎn)回來帶上的code
*
* @return openid
*/

private function getOpenidFromMp($code)
{

   $url = $this->__CreateOauthUrlForOpenid($code);
   //初始化curl
   $ch = curl_init();
   //設(shè)置超時(shí)
   curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout);
   curl_setopt($ch, CURLOPT_URL, $url);
   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
   curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE);
   curl_setopt($ch, CURLOPT_HEADER, FALSE);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
   if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0" && WxPayConfig::CURL_PROXY_PORT != 0){
       curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
       curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
   }
   //運(yùn)行curl,結(jié)果以jason形式返回
   $res = curl_exec($ch);
   curl_close($ch);
   //取出openid
   $data = json_decode($res, true);
   $this->data = $data;
   $openid = $data['openid'];
   return $openid;
}

/**
*
* 構(gòu)造獲取open和access_toke的url地址
* @param string $code,微信跳轉(zhuǎn)帶回的code
*
* @return 請(qǐng)求的url
*/

private function __CreateOauthUrlForOpenid($code)
{

   $urlObj["appid"] = WxPayConfig::APPID;
   $urlObj["secret"] = WxPayConfig::APPSECRET;
   $urlObj["code"] = $code;
   $urlObj["grant_type"] = "authorization_code";
   $bizString = $this->ToUrlParams($urlObj);
   return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
}

/**
*
* 拼接簽名字符串
* @param array $urlObj
*
* @return 返回已經(jīng)拼接好的字符串
*/

private function ToUrlParams($urlObj)
{

   $buff = "";
   foreach ($urlObj as $k => $v) {
       if ($k != "sign") {
           $buff .= $k . "=" . $v . "&";
       }
   }
   
   $buff = trim($buff, "&");
   return $buff;
}


退款回調(diào)

以上步驟之后微信支付就已經(jīng)完成了,如果用戶付款了后悔,找到平臺(tái)客戶,然后客服在商戶平臺(tái)進(jìn)行退款,這時(shí)候微信會(huì)有退款結(jié)果通知,在商戶平臺(tái)的【交易中心】->【退款配置】中設(shè)置通知url

然后在服務(wù)器端完成通知方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
* 退款通知回調(diào)
*
* @return void
*/

public function refund()
{

   $xml = file_get_contents("php://input");
   $obj = $this->fromXml($xml);

   if($obj['return_code'] != 'SUCCESS'){
       return $this->toXML(['return_code' => 'FAIL', 'return_msg' => '回調(diào)失敗']);
   }

   // 退款結(jié)果對(duì)重要的數(shù)據(jù)進(jìn)行了加密,商戶需要用商戶證書與商戶秘鑰進(jìn)行解密后才能獲得結(jié)果通知的內(nèi)容
   $string = $obj['req_info'];
   $data = base64_decode($string);
   $md5_key = md5(config('wxpay.key'));
   // AES解密
   $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_RAND);
   $res = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $md5_key, $data, MCRYPT_MODE_ECB, $iv);
   
   // 解密的字符串末尾多了 ^G 或 ^K 等雜亂字符 ,需去掉
   $res_arr = explode('</root>', $res);
   $req_info = $this->fromXml($res_arr[0].'</root>');
   
   //查詢訂單,判斷訂單真實(shí)性
   $order = OrderModel::where(['out_trade_no' => $req_info["out_trade_no"]])->find();
   if (!$order) {
       return $this->toXML(['return_code' => 'FAIL', 'return_msg' => '訂單不存在']);
   }

   $order->status = 2;
   if ($order->save()) {
       // TODO::存儲(chǔ)退款信息
       return $this->toXML(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
   }
   return $this->toXML(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
}

/**
* 將xml轉(zhuǎn)為array
*
* @param [type] $xml
* @return void
*/

public function fromXml($xml)
{  

   if(!$xml){
       return [];
   }
   //將XML轉(zhuǎn)為array
   //禁止引用外部xml實(shí)體
   libxml_disable_entity_loader(true);
   $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);      
   return $values;
}


在通知中主要是對(duì)訂單的狀態(tài)變換了一下,其次解析返回的加密數(shù)據(jù),可進(jìn)一步存儲(chǔ)退款信息。