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 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 }
注:本代码只做了微信支付,亲测可用