APP微信支付 前端uniapp 后端netcore 实现方法

时间:2024-02-23 08:14:29

APP微信支付 前端uniapp  后端netcore 实现方法

1、前端uniapp实现方法

2、前端代码uniapp

  1 <template>
  2     <view class="container">
  3         <view class="uni-padding-wrap">
  4             <view style="background:#FFF; padding:50rpx 0;">
  5                 <view class="uni-h1 uni-center uni-common-mt">
  6                     <text class="rmbLogo">¥</text>
  7                     <input class="price" type="digit" :value="price" maxlength="4" @input="priceChange" />
  8                 </view>
  9             </view>
 10             <view>
 11                 <view v-for="(item,index) in providerList" :key="index" @tap="requestPayment(item,index)">
 12                     {{item.name}}支付
 13                 </view>
 14             </view>
 15         </view>
 16     </view>
 17 </template>
 18 <script>
 19     export default {
 20         data() {
 21             return {
 22                 price: 1,
 23                 providerList: []
 24             }
 25         },
 26         onLoad: function() {
 27             // #ifdef APP-PLUS
 28             uni.getProvider({
 29                 service: "payment",
 30                 success: (e) => {
 31                     console.log("payment success:" + JSON.stringify(e));
 32                     let providerList = [];
 33                     e.provider.map((value) => {
 34                         switch (value) {
 35                             case \'alipay\':
 36                                 providerList.push({
 37                                     name: \'支付宝\',
 38                                     id: value,
 39                                     loading: false
 40                                 });
 41                                 break;
 42                             case \'wxpay\':
 43                                 providerList.push({
 44                                     name: \'微信\',
 45                                     id: value,
 46                                     loading: false
 47                                 });
 48                                 break;
 49                             default:
 50                                 break;
 51                         }
 52                     })
 53                     this.providerList = providerList;
 54                 },
 55                 fail: (e) => {
 56                     console.log("获取支付通道失败:", e);
 57                 }
 58             });
 59             // #endif
 60         },
 61         methods: {
 62             async requestPayment(e, index) {
 63                 this.providerList[index].loading = true;
 64                 let orderInfo = await this.getOrderInfo(e.id);
 65                 console.log("得到订单信息", orderInfo);
 66                 if (orderInfo.statusCode !== 200) {
 67                     console.log("获得订单信息失败", orderInfo);
 68                     uni.showModal({
 69                         content: "获得订单信息失败",
 70                         showCancel: false
 71                     })
 72                     return;
 73                 }
 74                 
 75                 uni.requestPayment({
 76                     provider: e.id,
 77                     orderInfo: orderInfo.data.Data,
 78                     success: (e) => {
 79                         console.log("success", e);
 80                         uni.showToast({
 81                             title: "感谢您的赞助!"
 82                         })
 83                     },
 84                     fail: (e) => {
 85                         console.log("fail", e);
 86                         uni.showModal({
 87                             content: "支付失败,原因为: " + e.errMsg,
 88                             showCancel: false
 89                         })
 90                     },
 91                     complete: () => {
 92                         this.providerList[index].loading = false;
 93                     }
 94                 })
 95             },
 96             getOrderInfo(e) {
 97                 let out_trade_no=\'订单号\';
 98                 let url = \'你的服务端apiURL/APP_Pay?type=1&out_trade_no=\'+out_trade_no+\'&total_fee=\' + this.price;
 99                 return new Promise((res) => {
100                     uni.request({
101                         url: url,
102                         success: (result) => {
103                             res(result);
104                             console.log(JSON.stringify(result));
105                         },
106                         fail: (e) => {
107                             res(e);
108                             console.log("eee:" + JSON.stringify(e));
109                         }
110                     })
111                 })
112             },
113             priceChange(e) {
114                 console.log(e.detail.value)
115                 this.price = e.detail.value;
116             }
117         }
118     }
119 </script>
120 
121 <style>
122     .price {
123         border-bottom: 1px solid #eee;
124         width: 200rpx;
125         height: 80rpx;
126         padding-bottom: 4rpx;
127     }
128 </style>

3、后端netcore

  1 using Microsoft.AspNetCore.Http;
  2 using Microsoft.AspNetCore.Mvc;
  3 using System;
  4 using System.Collections.Generic;
  5 using System.Security.Cryptography;
  6 using System.Text;
  7 using System.Xml;
  8 
  9 namespace YiSha.Admin.WebApi.Controllers
 10 {
 11     [Route("[controller]/[action]")]
 12     [ApiController]
 13     [AuthorizeFilter]
 14     public class AppPayController : ControllerBase
 15     {
 16         //请求方式:http get
 17         //接口参数说明
 18         //名称    类型 必填    说明
 19         //out_trade_no    string 是    支付订单ID
 20         //total_fee    Double 是    支付金额
 21         //type    int 是    1.安卓,2.IOS
 22 
 23         //返回示例:
 24         ///****失败示例**/
 25         //{
 26         //"Code":1, /*状态码  1:失败 2:成功 */
 27         //"Message":"错误信息",/*消息(一般失败时,返回错误信息)*/
 28         //"Tag":""/*附加信息*/
 29         //}
 30         ///****成功示例**/
 31         //{
 32         //"Code":2, /*状态码  1:失败 2:成功*/
 33         //“Data”:[]
 34         //"Message":"",/*消息(一般失败时,返回错误信息)*/
 35         //"Tag":"附加信息"/* */
 36         //}
 37         //接口返回Data集合参数说明
 38         //名称    类型 说明
 39         //appid string 应用ID
 40         //partnerid String     商户号
 41         //prepayid    String 预支付交易会话ID
 42         //package String    扩展字段
 43         //noncestr    String 随机字符串
 44         //timestamp String    时间戳
 45         //sign    String 签名
 46 
 47         #region 微信APP支付接口
 48         /// <summary>
 49         /// APP_Pay微信APP支付接口
 50         /// </summary>
 51         /// <param name="out_trade_no">支付订单号</param
 52         /// <param name="total_fee">支付金额</param>
 53         /// <param name="type">1.安卓,2.IOS</param>
 54         /// <returns></returns>
 55         [HttpGet]
 56 
 57         public CommonResponse<Wx_pay> APP_Pay(string out_trade_no, Double total_fee, int type)
 58         {
 59             PayMent pm = new PayMent();
 60             HttpContextAccessor context = new HttpContextAccessor();
 61             string ip = context.HttpContext?.Connection.RemoteIpAddress.ToString();
 62             int money = int.Parse((total_fee * 100).ToString());
 63             Wx_pay wp = pm.APP_PayMent("服务费", ip, money, out_trade_no, type);
 64             if (wp.sign == "")
 65             {
 66                 return new CommonResponse<Wx_pay> { Data = null, Message = "系统异常,联系管理员!", Code = 1 };
 67             }
 68             return new CommonResponse<Wx_pay> { Data = wp, Message = String.Empty, Code = 2 };
 69         }
 70         #endregion
 71     }
 72     ///
 73     ///是对返回数据类型
 74     ///
 75     public class CommonResponse<T>
 76     {
 77         /// <summary>
 78         /// 数据
 79         /// </summary>
 80         public T Data { get; set; }
 81         /// <summary>
 82         /// 代码  1:失败,2:成功
 83         /// </summary>
 84         public int Code { get; set; }
 85         /// <summary>
 86         /// 消息
 87         /// </summary>
 88         public string Message { get; set; }
 89         /// <summary>
 90         /// 其他附带信息
 91         /// </summary>
 92         public string Tag { get; set; }
 93     }
 94 
 95     /// <summary>
 96     /// 微信APP支付实体
 97     /// </summary>
 98     public class Wx_pay
 99     {
100         /// <summary>
101         /// 应用ID
102         /// </summary>
103         public string appid { set; get; } = "";
104         /// <summary>
105         /// 商户号
106         /// </summary>
107         public string partnerid { set; get; } = "";
108         /// <summary>
109         /// 预支付交易会话ID
110         /// </summary>
111         public string prepayid { set; get; } = "";
112         /// <summary>
113         /// 扩展字段
114         /// </summary>
115         public string package { set; get; } = "Sign=WXPay";
116         /// <summary>
117         /// 随机字符串
118         /// </summary>
119         public string noncestr { set; get; } = "";
120         /// <summary>
121         /// 时间戳
122         /// </summary>
123         public string timestamp { set; get; } = "";
124 
125         /// <summary>
126         /// 签名
127         /// </summary>
128         public string sign { set; get; } = "";
129     }
130 
131     /// <summary>
132     /// 
133     /// </summary>
134     public class PayMent {
135         #region 微信APP支付
136         /// <summary>
137         /// 微信APP支付
138         /// </summary>
139         /// <param name="boby">商品描述</param>
140         /// <param name="mch_id">商户号</param>
141         /// <param name="spbill_create_ip">终端IP</param>
142         /// <param name="total_fee">金额</param>
143         /// <param name="out_trade_no">商户订单号</param>
144         /// <param name="type">1安卓2苹果</param>
145         /// <returns></returns>
146         public Wx_pay APP_PayMent(string boby, string spbill_create_ip, int total_fee, string out_trade_no, int type)
147         {
148             UnifiedOrder order = new UnifiedOrder();
149             if (type == 1)
150             {
151                 order.appid = APP_Aconfig.appid;
152                 order.mch_id = APP_Aconfig.partnerid;
153             }
154             else
155             {
156                 order.appid = APP_Iconfig.appid;
157                 order.mch_id = APP_Iconfig.partnerid;
158             }
159             order.attach = "APP名称-支付内容说明";
160             order.body = boby;
161             order.device_info = "WEB";
162             order.nonce_str = TenpayUtil.getNoncestr();
163             order.notify_url = APP_Aconfig.url;
164             order.out_trade_no = out_trade_no;
165             order.trade_type = "APP";
166             order.spbill_create_ip = spbill_create_ip;
167             order.total_fee = total_fee;
168             TenpayUtil tenpay = new TenpayUtil();
169             string paySignKey = string.Empty;
170             if (type == 1)
171             {
172                 paySignKey = APP_Aconfig.paysignkey;
173             }
174             else
175             {
176                 paySignKey = APP_Iconfig.paysignkey;
177             }
178             string prepay_id = tenpay.getPrepay_id(order, paySignKey);
179             string timeStamp = TenpayUtil.getTimestamp();
180             string nonceStr = TenpayUtil.getNoncestr();
181             SortedDictionary<string, object> sParams = new SortedDictionary<string, object>();
182             sParams.Add("appid", order.appid);
183             sParams.Add("partnerid", order.mch_id);
184             sParams.Add("prepayid", prepay_id);
185             sParams.Add("noncestr", nonceStr);
186             sParams.Add("timestamp", timeStamp);
187             sParams.Add("package", "Sign=WXPay");
188             string paySign = tenpay.getsign(sParams, paySignKey);
189             Wx_pay wp = new Wx_pay();
190             wp.appid = order.appid;
191             wp.partnerid = order.mch_id;
192             wp.noncestr = nonceStr;
193             wp.prepayid = prepay_id;
194             wp.sign = paySign;
195             wp.timestamp = timeStamp;
196             return wp;
197         }
198         #endregion
199     }
200     /// <summary>
201     /// APP安卓支付配置
202     /// </summary>
203     public class APP_Aconfig
204     {
205         public const string appid = "";//APPID
206         public const string partnerid = "";//商户号
207         public const string paysignkey = ""; //证书密匙商户平台APIkey
208         public const string url = "";//回调ur
209     }
210 
211     /// <summary>
212     /// APPios 支付配置
213     /// </summary>
214     public class APP_Iconfig
215     {
216         public const string appid = "";//APPID
217         public const string partnerid = "";//商户号
218         public const string paysignkey = "";//证书密匙
219         public const string url = "";//回调url
220     }
221     //-------TenpayUtil类
222     /// <summary>
223     /// 
224     /// </summary>
225     public class TenpayUtil
226     {
227         /// <summary>
228         /// 统一支付接口
229         /// </summary>
230         const string UnifiedPayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
231         /// <summary>
232         /// 随机串
233         /// </summary>
234         public static string getNoncestr()
235         {
236             Random random = new Random();
237             return MD5Util.GetMD5(random.Next(1000).ToString(), "GBK").ToLower().Replace("s", "S");
238         }
239 
240         /// <summary>
241         /// 时间截,自1970年以来的秒数
242         /// </summary>
243 
244         public static string getTimestamp()
245         {
246             TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
247             return Convert.ToInt64(ts.TotalSeconds).ToString();
248         }
249 
250         /// <summary>
251         /// 获取微信签名
252         /// </summary>
253         /// <param name="sParams"></param>
254         /// <returns></returns>
255 
256         public string getsign(SortedDictionary<string, object> sParams, string key)
257         {
258             int i = 0;
259             string sign = string.Empty;
260             StringBuilder sb = new StringBuilder();
261             foreach (KeyValuePair<string, object> temp in sParams)
262             {
263                 if (temp.Value.ToString() == "" || temp.Value == null || temp.Key.ToLower() == "sign")
264                 {
265                     continue;
266                 }
267                 i++;
268                 sb.Append(temp.Key.Trim() + "=" + temp.Value.ToString() + "&");
269             }
270             sb.Append("key=" + key.Trim() + "");
271             string signkey = sb.ToString();
272             sign = MD5Util.GetMD5(signkey, "utf-8");
273             return sign;
274         }
275 
276         /// <summary>
277         /// post数据到指定接口并返回数据
278         /// </summary>
279 
280         public string PostXmlToUrl(string url, string postData)
281         {
282             string returnmsg = "";
283             using (System.Net.WebClient wc = new System.Net.WebClient())
284             {
285                 returnmsg = wc.UploadString(url, "POST", postData);
286             }
287             return returnmsg;
288         }
289 
290         /// <summary>
291         /// 获取prepay_id
292         /// </summary>
293 
294         public string getPrepay_id(UnifiedOrder order, string key)
295         {
296             string prepay_id = "";
297             string post_data = getUnifiedOrderXml(order, key);
298             string request_data = PostXmlToUrl(UnifiedPayUrl, post_data);
299             SortedDictionary<string, object> requestXML = GetInfoFromXml(request_data);
300             foreach (KeyValuePair<string, object> k in requestXML)
301             {
302                 if (k.Key == "prepay_id")
303                 {
304                     prepay_id = k.Value.ToString();
305                     break;
306                 }
307             }
308             return prepay_id;
309         }
310 
311         /// <summary>
312         /// 把XML数据转换为"SortedDictionary<string, string>"集合
313         /// </summary>
314         /// <param name="strxml"></param>
315         /// <returns>
316         /// 
317         /// </returns>
318         protected SortedDictionary<string, object> GetInfoFromXml(string xmlstring)
319         {
320             SortedDictionary<string, object> sParams = new SortedDictionary<string, object>();
321             try
322             {
323                 XmlDocument doc = new XmlDocument();
324                 doc.LoadXml(xmlstring);
325                 XmlElement root = doc.DocumentElement;
326                 int len = root.ChildNodes.Count;
327                 for (int i = 0; i < len; i++)
328                 {
329                     string name = root.ChildNodes[i].Name;
330                     if (!sParams.ContainsKey(name))
331                     {
332                         sParams.Add(name.Trim(), root.ChildNodes[i].InnerText.Trim());
333                     }
334                 }
335             }
336             catch { }
337             return sParams;
338         }
339 
340         /// <summary>
341         /// 微信统一下单接口xml参数整理
342         /// </summary>
343         /// <param name="order">微信支付参数实例</param>
344         /// <param name="key">密钥</param>
345         /// <returns></returns>
346 
347         protected string getUnifiedOrderXml(UnifiedOrder order, string key)
348         {
349             string return_string = string.Empty;
350             SortedDictionary<string, object> sParams = new SortedDictionary<string, object>();
351             sParams.Add("appid", order.appid);
352             sParams.Add("attach", order.attach);
353             sParams.Add("body", order.body);
354             sParams.Add("device_info", order.device_info);
355             sParams.Add("mch_id", order.mch_id);
356             sParams.Add("nonce_str", order.nonce_str);
357             sParams.Add("notify_url", order.notify_url);
358             sParams.Add("openid", order.openid);
359             sParams.Add("out_trade_no", order.out_trade_no);
360             sParams.Add("spbill_create_ip", order.spbill_create_ip);
361             sParams.Add("total_fee", order.total_fee);
362             sParams.Add("trade_type", order.trade_type);
363             order.sign = getsign(sParams, key);
364             sParams.Add("sign", order.sign);
365             //拼接成XML请求数据
366             StringBuilder sbPay = new StringBuilder();
367             foreach (KeyValuePair<string, object> k in sParams)
368             {
369                 if (k.Key == "attach" || k.Key == "body" || k.Key == "sign")
370                 {
371                     sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">");
372                 }
373                 else
374                 {
375                     sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">");
376                 }
377             }
378             return_string = string.Format("<xml>{0}</xml>", sbPay.ToString());
379             return return_string;
380         }
381     }
382 
383     //---微信统一接口请求实体对象
384     /// <summary>
385     /// 微信统一接口请求实体对象
386     /// </summary>
387     [Serializable]
388     public class UnifiedOrder
389     {
390         /// <summary>
391         /// 公众号ID(微信分配的公众账号 ID)
392         /// </summary>
393         public string appid = "";
394         /// <summary>
395         /// 商户号(微信支付分配的商户号)
396         /// </summary>
397         public string mch_id = "";
398         /// <summary>
399         /// 微信支付分配的终端设备号
400         /// </summary>
401         public string device_info = "";
402         /// <summary>
403         /// 随机字符串,不长于 32 位
404         /// </summary>
405         public string nonce_str = "";
406         /// <summary>
407         /// 签名
408         /// </summary>
409         public string sign = "";
410         /// <summary>
411         /// 商品描述
412         /// </summary>
413         public string body = "";
414         /// <summary>
415         /// 附加数据,原样返回
416         /// </summary>
417         public string attach = "";
418         /// <summary>
419         /// 商户系统内部的订单号,32个字符内、可包含字母,确保在商户系统唯一,详细说明
420         /// </summary>
421         public string out_trade_no = "";
422         /// <summary>
423         /// 订单总金额,单位为分,不能带小数点
424         /// </summary>
425         public int total_fee = 0;
426         /// <summary>
427         /// 终端IP
428         /// </summary>
429         public string spbill_create_ip = "";
430         /// <summary>
431         /// 订 单 生 成 时 间 , 格 式 为yyyyMMddHHmmss,如 2009 年12 月 25 日 9 点 10 分 10 秒表示为 20091225091010。时区为 GMT+8 beijing。该时间取自商户服务器
432         /// </summary>
433         public string time_start = "";
434         /// <summary>
435         /// 交易结束时间
436         /// </summary>
437         public string time_expire = "";
438         /// <summary>
439         /// 商品标记 商品标记,该字段不能随便填,不使用请填空,使用说明详见第 5 节
440         /// </summary>
441         public string goods_tag = "";
442         /// <summary>
443         /// 接收微信支付成功通知
444         /// </summary>
445         public string notify_url = "";
446         /// <summary>
447         /// JSAPI、NATIVE、APP
448         /// </summary>
449         public string trade_type = "";
450         /// <summary>
451         /// 用户标识 trade_type 为 JSAPI时,此参数必传
452         /// </summary>
453         public string openid = "";
454         /// <summary>
455         /// 只在 trade_type 为 NATIVE时需要填写。
456         /// </summary>
457         public string product_id = "";
458 
459     }
460     /// <summary>
461     /// 
462     /// </summary>
463     public class MD5Util
464     {
465         /// <summary>
466         /// 
467         /// </summary>
468         public MD5Util()
469         {
470             //
471             // TODO: 在此处添加构造函数逻辑
472             //
473         }
474         /// <summary>
475         /// /** 获取大写的MD5签名结果 */
476         /// </summary>
477         /// <param name="encypStr">数据</param>
478         /// <param name="charset">编码格式</param>
479         /// <returns></returns>
480 
481 
482         public static string GetMD5(string encypStr, string charset)
483         {
484             string retStr;
485             MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();
486 
487             //创建md5对象
488             byte[] inputBye;
489             byte[] outputBye;
490 
491             //使用GB2312编码方式把字符串转化为字节数组.
492             try
493             {
494                 inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr);
495             }
496             catch (Exception ex)
497             {
498                 inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
499             }
500             outputBye = m5.ComputeHash(inputBye);
501             retStr = System.BitConverter.ToString(outputBye);
502             retStr = retStr.Replace("-", "").ToUpper();
503             return retStr;
504         }
505         /// <summary>
506         /// SHA1加密
507         /// </summary>
508         /// <param name="str"></param>
509         /// <returns></returns>
510         //public static string sha1(string str)
511         //{
512         //    return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "sha1").ToLower();
513         //}
514         // 转JSon对象
515 
516         /// <summary>
517         /// json
518         /// </summary>
519         /// <returns></returns>
520 
521         public static String toJson(string appId, string timeStamp, string nonceStr, string packageA, string signType, string paySign)
522         {
523             String json = "{";
524             json += "\"appId\":" + "\"" + appId + "\",";
525             json += "\"timeStamp\":" + "\"" + timeStamp + "\",";
526             json += "\"nonceStr\":" + "\"" + nonceStr + "\",";
527             json += "\"package\":" + "\"" + packageA + "\",";
528             json += "\"signType\":" + "\"" + signType + "\",";
529             json += "\"paySign\":" + "\"" + paySign + "\"";
530             json += "}";
531             return json;
532         }
533 
534         /// <summary>
535         /// string转utf-8
536         /// </summary>
537         /// <param name="unicodeString"></param>
538         /// <returns></returns>
539         public static string get_uft8(string unicodeString)
540         {
541             UTF8Encoding utf8 = new UTF8Encoding();
542             Byte[] encodedBytes = utf8.GetBytes(unicodeString);
543             String decodedString = utf8.GetString(encodedBytes);
544             return decodedString;
545         }
546     }
547 
548 }

 

注:本代码只做了微信支付,亲测可用