不明白可以直接评论留言
详见微信支付-开发文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_sl_api.php?chapter=9_1
/**
* @Notes: 小程序服务商支付模式 测试(完)
* @Date: 2020-10-19 16:13
*/
public function add_pay()
{
$appid = $this->mch_appid; // 服务商的APPID
$mch_id = $this->mch_id; // 微信支付分配的商户号
$key = $this->key; // 服务商户支付秘钥
$sub_appid = $this->appid; //当前调起支付的小程序APPID
$sub_mch_id = $this->sub_mch_id; // 微信支付分配的子商户号 子商户号
$body = "测试";
$out_trade_no = "1415659990";//订单号
$openid = $this->userInfo['openid']??"";// 用户openid
$total_fee = 0.01;// 支付金额
$notify_url = "/";//支付成功回掉
$res = Pay::get_pay($appid, $mch_id, $key, $sub_appid, $sub_mch_id, $body, $out_trade_no, $openid, $total_fee, $notify_url);
}
pay 文件
<?php
/**
* Desc:小程序服务商支付模式
* Date: 2020-10-19 13:18
*/
namespace app\model;
use think\Db;
use think\Cache;
use think\Exception;
use think\facade\Config;
use think\Request;
class Pay
{
/**
* @Notes: 订单支付
* @Date: 2020-10-19 13:20
* $appid 服务商的APPID
* $mch_id 商户号
* $key 服务商key
* $sub_appid 小程序的APPID
* $sub_mch_id 子商户号
* $body 商品描述
* $out_trade_no 商户订单号
* $openid 用户标示
* $total_fee 货币类型
* $notify_url 通知地址
*/
public static function get_pay($appid = '', $mch_id = '', $key = '', $sub_appid = '', $sub_mch_id = '', $body = '', $out_trade_no = '', $openid = '', $fee = 0.00, $notify_url = '')
{
$ip = $_SERVER['SERVER_ADDR'];
$nonce_str = nonce_str();//随机字符串
$spbill_create_ip = $ip;//服务器IP
$trade_type = 'JSAPI';//交易类型 默认
$total_fee = $fee * 100;// 微信支付单位是分,所以这里需要*100
//这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错
$post['appid'] = $appid;
$post['body'] = $body;
$post['mch_id'] = $mch_id;
$post['nonce_str'] = $nonce_str; //随机字符串
$post['notify_url'] = $notify_url;
$post['sub_openid'] = $openid; //支付者在子商户的openid
$post['out_trade_no'] = $out_trade_no;
$post['spbill_create_ip'] = $spbill_create_ip; //终端的ip
$post['sub_appid'] = $sub_appid;
$post['sub_mch_id'] = $sub_mch_id;
$post['total_fee'] = $total_fee; //总金额 最低为一块钱 必须是整数
$post['trade_type'] = $trade_type;
// p($post,1);
$sign = Dev::get_sign($post, $key);
$post_xml = "<xml>
<appid>$appid</appid>
<body>$body</body>
<mch_id>$mch_id</mch_id>
<nonce_str>$nonce_str</nonce_str>
<notify_url>$notify_url</notify_url>
<out_trade_no>$out_trade_no</out_trade_no>
<spbill_create_ip>$spbill_create_ip</spbill_create_ip>
<sub_appid>$sub_appid</sub_appid>
<sub_mch_id>$sub_mch_id</sub_mch_id>
<sub_openid>$openid</sub_openid>
<total_fee>$total_fee</total_fee>
<trade_type>$trade_type</trade_type>
<sign>$sign</sign>
</xml>";
//统一接口prepay_id
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$xml = http_request($url, $post_xml);
$array = self::xml($xml);//全要大写
write_log($array, 'get_pay');
if ($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS') {
$time = time();
$tmp = [];//临时数组用于签名
//$tmp['appId'] = $appid;
$tmp['appId'] = $sub_appid;
$tmp['nonceStr'] = $nonce_str;
$tmp['package'] = 'prepay_id=' . $array['PREPAY_ID'];
$tmp['signType'] = 'MD5';
$tmp['timeStamp'] = "$time";
$data['state'] = 1;
$data['timeStamp'] = "$time";//时间戳
$data['nonceStr'] = $nonce_str;//随机字符串
$data['signType'] = 'MD5';//签名算法,暂支持 MD5
$data['package'] = 'prepay_id=' . $array['PREPAY_ID'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
$data['paySign'] = Dev::get_sign($tmp, $key);//签名,具体签名方案参见微信公众号支付帮助文档;
$data['out_trade_no'] = $out_trade_no;
} else {
$data['state'] = 0;
$data['text'] = "错误";
$data['RETURN_CODE'] = $array['RETURN_CODE'];
$data['RETURN_MSG'] = $array['RETURN_MSG'];
}
return json_encode($data);
}
//获取xml
private static function xml($xml)
{
$p = xml_parser_create();
xml_parse_into_struct($p, $xml, $vals, $index);
xml_parser_free($p);
$data = [];
foreach ($index as $key => $value) {
if ($key == 'xml' || $key == 'XML') continue;
$tag = $vals[$value[0]]['tag'];
$value = $vals[$value[0]]['value'];
$data[$tag] = $value;
}
return $data;
}
}
//随机32位字符串
function nonce_str()
{
$result = '';
$str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
for ($i = 0; $i < 32; $i++) {
$result .= $str[rand(0, 48)];
}
return $result;
}
/**
* curl请求
* @param $url
* @param null $data
* @param array $headers
* @return bool|string
*/
function http_request($url, $data = null, $headers = array())
{
$curl = curl_init();
if (count($headers) >= 1) {
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)) {
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
Dev文件
<?php
/**
* 生成微信签名
* Date: 2020-10-19
* Time: 10:41
*/
namespace app\model;
class Dev
{
//作用:生成签名
public static function get_sign($params, $secret) {
foreach ($params as $k => $v) {
$Parameters[$k] = $v;
}
//签名步骤一:按字典序排序参数
ksort($Parameters);
$String = self::formatBizQueryParaMap($Parameters, false);
//签名步骤二:在string后加入KEY
$String = $String . "&key=" . $secret;
//签名步骤三:MD5加密
$String = md5($String);
//签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
return $result_;
}
///作用:格式化参数,签名过程需要使用
public static function formatBizQueryParaMap($paraMap, $urlencode) {
$buff = "";
ksort($paraMap);
foreach ($paraMap as $k => $v) {
if ($urlencode) {
$v = urlencode($v);
}
$buff .= $k . "=" . $v . "&";
}
$reqPar="";
if (strlen($buff) > 0) {
$reqPar = substr($buff, 0, strlen($buff) - 1);
}
return $reqPar;
}
}