微信小程序中JSAPI支付

180 阅读1分钟

最近使用uniapp做小程序微信支付功能,翻遍了互联网几乎没有正确靠谱的解决方案,现在使用的是v3版本。

首先uniapp 部分

获取用户的openId

				uni.login({
					provider: 'weixin',
					success: function(loginRes) {
						为了获取 用户的openId
						console.log(loginRes.code);
					}
				});

```				https
通过code获取openId
https: //api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=secret&js_code=code&grant_type=authorization_code


```js

  let data = {
  mchid: "商户号",
  out_trade_no: "222222222",
  appid: "appid",
  description: '1111111',
  notify_url: "https://www.c21w.com",
  amount: {
   total: 1,
   currency: 'CNY',
  },
  payer: {
   openid: "刚刚获取的openid",
  }
 }

uni.request({
 url: "http://localhost:801/pay.php",
 method: "POST",
 data: {
  url: "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi",
  data: JSON.stringify(data),
  http_method: "POST",
 },
 success: (res) => {
  let timestamp = String(res.data.timestamp)
  let nonce = res.data.nonce
  uni.request({
   url: "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi",
   method: "POST",
   header: {
    "Accept": "*/*",
    'Authorization': "WECHATPAY2-SHA256-RSA2048 " + res.data.token,
   },
   data: res.data.data,
   success: (r) => {
    let prepay_id = r.data.prepay_id

    uni.request({
     url: "http://localhost:801/sign.php",
     data: {
      timestamp: timestamp,
      nonce: nonce,
      prepay_id: "prepay_id=" + prepay_id
     },
     success: (result) => {
      let sign = result.data.sign;
      console.log(JSON.stringify(result), 333)
      wx.requestPayment({

       "timeStamp": timestamp,
       "nonceStr": nonce,
       "package": 'prepay_id=' + prepay_id,
       "signType": "RSA",
       "paySign": sign,
       success: (s) => {
        console.log()
       },
       fail: (f) => {
        console.log(f)
       }
      })
     }
    })
   }
  })

 }
})

php 部分 pay.php


//微信支付API证书序列号
$serial_no="serial_no";
//商户ID
$mchid="mchid";
//$body是用于接收前端请求携带的参数
$body=json_decode(file_get_contents("php://input"),true);
//请求接口的请求方式
$http_method=$body['http_method'];
//生成时间戳
$timestamp = time();
//生成随机数
$nonce=(randomString(32));
//接收需要给接口发起请求携带的请求体
$data=$body['data'];
//接口url
$url=$body['url'];
$url_parts = parse_url($url);
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
$message = $http_method."\n".
    $canonical_url."\n".
    $timestamp."\n".
    $nonce."\n".
    $data."\n";


//获取私钥文件
$mch_private_key = file_get_contents('./cert/apiclient_key.pem');
//生成签名
openssl_sign($message, $raw_sign,$mch_private_key, 'sha256WithRSAEncryption');
$sign =base64_encode($raw_sign);
$token=sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
    $mchid, $nonce,  $timestamp, $serial_no,$sign);
//输出数据
print_r(json_encode(["msg"=>"预订单生成成功","code"=>200,"token"=>$token,"data"=>$data,"timestamp"=>$timestamp,"nonce"=>$nonce]));
// 生成随机字符串函数
function randomString($len = 32)
{
    $string = '';
    $char = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
    for ($i = 0; $i < $len; $i++) {
        $string .= $char[mt_rand(0, strlen($char) - 1)];
    }
    return $string;
}

sign.php 部分

//你的小程序appid
$appid="appid";
//用于接收前端发起请求携带的参数
$body=json_decode(file_get_contents("php://input"),true);
//用户对JSAPI下单接口发起请求后得到的prepay_id
$prepay_id=$_GET['prepay_id'];
//时间戳
$timestamp =$_GET['timestamp'];
//随机字符串

$nonce= ($_GET['nonce']);


$message = $appid."\n".
    $timestamp."\n".
    $nonce."\n".
    $prepay_id."\n";

//获取私钥文件
$mch_private_key = file_get_contents('./cert/apiclient_key.pem');
// 生成签名
openssl_sign($message, $raw_sign,$mch_private_key, 'sha256WithRSAEncryption');

$sign = base64_encode($raw_sign);
print_r(json_encode(["msg"=>"签名成功","code"=>200,"sign"=>$sign]));