前提: 要已注册微信商户号和已申请小程序支付功能。否则,请先去申请小程序微信支付功能 和 注册商家商户信息
一、配置信息
1、登录微信公众平台:mp.weixin.qq.com
2、获取到小程序的:appId,secret
3、获取到商户号和key:mchId,key
二、实现思路
1、微信用户通过 wx.login 获取到 code 去后端请求用户所在小程序对应的 openId
2、小程序通过用户 openId 和 支付金额 访问后端去微信下单订单生成预支付交易会话标识:prepay_id ,并在后端组装一个 微信支付定义的数据对象 返回给小程序
3、小程序通过后端返回的 微信数据对象 去使用 wx.requestPayment 支付接口实现输入密码支付功能
小程序下单支付官方文档 :小程序下单 - 小程序支付 | 微信支付商户文档中心 (qq.com)
三、代码实现
配置信息
c
//所需值
static string _appid = "wx*******b";//小程序ID
static string _secret = "9ec*******dada";//小程序App/Secret
static string _mch_id = "1*******4";//商户号
static string _key = "yc*******11";//微信支付的Key/Secret
//获取token地址
static string getOpenId = "https://api.weixin.qq.com/sns/jscode2session?
appid={0}&secret={1}&grant_type=authorization_code&js_code={2}";
1、后端代码
1.1、获取用户openId
csharp
/// <summary>
/// 获取用户openId
/// </summary>
/// <param name="js_code">通过wx.login获取到的code</param>
/// <returns></returns>
[HttpGet("GetOpenId")]
public string GetOpenId(string js_code)
{
string url = string.Format(getOpenId, _appid, _secret ,js_code);
WebClient wc = new WebClient();
Encoding enc = Encoding.GetEncoding("UTF-8");
Byte[] pageData = wc.DownloadData(url);
return enc.GetString(pageData);
}
1.2、进行微信小程序下单获取预支付标识prepay_id 并组装微信支付数据对象返回给前端
ini
/// <summary>
/// 模拟wx统一下单
/// </summary>
/// <param name="openid">前台获取用户标识</param>
/// <returns></returns>
[HttpGet]
public string Get(string openid, decimal amount)
{
string notify_url = "http://www.weixin.qq.com/wxpay/pay.php";//微信支付通知地址
string attach = "附加数据";//附加数据,自定义数据说明
var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信统一下单请求地址
string body = "JSAPI支付测试";
int total_fee = Convert.ToInt32(amount * 100);//支付金额,需要输入的金额*100 是微信接收的金额
#region 生成随机串
const string key = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
Random rnd = new Random();
byte[] buffer = new byte[8];
ulong bit = 31;
ulong result = 0;
int index = 0;
StringBuilder _nonce_str = new StringBuilder(32);
while (_nonce_str.Length < 32)
{
rnd.NextBytes(buffer);
buffer[5] = buffer[6] = buffer[7] = 0x00;
result = BitConverter.ToUInt64(buffer, 0);
while (result > 0 && _nonce_str.Length < 32)
{
index = (int)(bit & result);
_nonce_str.Append(key[index]);
result = result >> 5;
}
}
string nonce_str = _nonce_str.ToString();
#endregion
#region 生成随机订单号
Random rd = new Random();//用于生成随机数
string DateStr = DateTime.Now.ToString("yyyyMMddHHmmssMM");//日期
string bookingNo = DateStr + rd.Next(10000).ToString().PadLeft(4, '0');//带日期的随机数
#endregion
string strk = "appid=" + _appid + "&attach="+ attach + "&body="+ body + "&mch_id=" + _mch_id + "&nonce_str=" + nonce_str + "¬ify_url=" + notify_url +
"&openid=" + openid + "&out_trade_no=" + bookingNo + "&spbill_create_ip=61.50.221.43&total_fee=" + total_fee + "&trade_type=JSAPI&key="+ _key;
#region 签名 数据组装
var formData = "<xml>";
formData += "<appid>" + _appid + "</appid>";//appid
formData += "<attach>" + attach + "</attach>"; //附加数据(描述)
formData += "<body>" + body + "</body>";//商品描述
formData += "<mch_id>" + _mch_id + "</mch_id>";//商户号
formData += "<nonce_str>" + nonce_str + "</nonce_str>";//随机字符串,不长于32位。
formData += "<notify_url>" + notify_url + "</notify_url>";//通知地址
formData += "<openid>" + openid + "</openid>";//openid
formData += "<out_trade_no>" + bookingNo + "</out_trade_no>";//商户订单号
formData += "<spbill_create_ip>61.50.221.43</spbill_create_ip>";//终端IP
formData += "<total_fee>" + total_fee + "</total_fee>";//支付金额单位为(分)
formData += "<trade_type>JSAPI</trade_type>";//交易类型(JSAPI--公众号支付)
formData += "<sign>" + MD5(strk).ToUpper() + "</sign>"; //签名
formData += "</xml>";
#endregion
#region 发送请求数据,去微信进行下单 获取prepay_id预支付标识
WebClient wCient = new WebClient();
wCient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
byte[] responseData = wCient.UploadData(url, "POST", Encoding.UTF8.GetBytes(formData));
//微信返回接收的数据
string getdata = Encoding.UTF8.GetString(responseData);
#endregion
//获取xml数据
XmlDocument doc = new XmlDocument();
doc.LoadXml(getdata);
//xml格式转json
string json = JsonConvert.SerializeXmlNode(doc);
JObject jo = (JObject)JsonConvert.DeserializeObject(json);
string prepay_id = jo["xml"]["prepay_id"]["#cdata-section"].ToString();
//时间戳
TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
string _time = Convert.ToInt64(ts.TotalSeconds).ToString();
//再次签名返回数据至小程序
string strB = "appId=" + _appid + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + _time + "&key=" + _key;
//wx自己写的一个类
//向小程序返回json数据
return JsonConvert.SerializeObject(new
{
timeStamp = _time,
nonceStr = nonce_str,
package = "prepay_id=" + prepay_id,
paySign = MD5(strB).ToUpper(),
signType = "MD5",
});
}
MD5加密数据方法
csharp
/// <summary>
/// MD5签名方法
/// </summary>
/// <param name="inputText">加密参数</param>
/// <returns></returns>
private static string MD5(string inputText)
{
MD5 md5 = new MD5CryptoServiceProvider();
byte[] fromData = System.Text.Encoding.UTF8.GetBytes(inputText);
byte[] targetData = md5.ComputeHash(fromData);
string byte2String = null;
for (int i = 0; i < targetData.Length; i++)
{
byte2String += targetData[i].ToString("x2");
}
return byte2String;
}
2、前端代码
2.1、页面代码,一个输入金额的文本框,一个支付按钮
ini
<view class='add_btn'>
<input class="weui-input" style="margin-left: 20px;margin-right:20px;" type="number" bindinput="inputvalue" placeholder="¥请输入充值金额" />
<button style="width:100vw;margin-top:20px;" bindtap="payment" class="btn"> 支付 </button>
</view>
2.2、方法代码
javascript
Page({
//获取openid
payment: function() {
var that = this;
wx.login({
success: res => {
if (res.code) {
//console.log('临时登录凭证code:' + res.code);
wx.request({
url: 'https://localhost:7033/api/WeChatPay/GetOpenId?js_code=' + res.code,
method: 'GET',
header: {
'content-type': 'application/json'
},
success: function(openIdRes) {
var openid = openIdRes.data.openid;
console.info("登录成功返回的openId:" + openid);
that.generateOrder(openid)
},
fail: function(error) {
console.info(error);
}
})
}
}
})
},
//生成商户订单
generateOrder: function(e) {
var that = this;
wx.request({
url: 'https://localhost:7033/api/WeChatPay',
data: {
openid: e, //用户openId
amount: 0.01 //支付金额
},
method: 'GET',
header: {
'content-type': 'application/json'
},
success: function (param) {
//调起微信小程序输入密码支付弹窗进行支付
that.zf(param);
},
fail: function(error) {
console.info(error);
}
})
},
//调起微信小程序输入密码支付弹窗进行支付
zf: function (param) {
console.log("发起支付")
wx.requestPayment({
timeStamp: param.data.timeStamp, //北京时间 时间戳
nonceStr: param.data.nonceStr, //随机字符串,不得长于32位
package: param.data.package, //小程序下单返回的预支付标识 prepay_id
signType: param.data.signType, //签名类型
paySign: param.data.paySign, //签名签名,使用字段`appid`、`timeStamp`、`nonceStr`、`package`计算得出的签名值,签名所使用的`appid`,为【小程序下单】时传入的`appid`,微信支付会校验下单与调起支付所使用的`appid`的一致性。
success: function (res) {
console.log(res);
},
fail: function (res) {
console.log(res);
},
complete: function (res) {
console.log(res)
}
})
}
})
三、效果实现
以上就是微信小程序支付的全部流程了!!!