微信APP支付(IOS手机端+java后台)版

http://blog.csdn.net/u012131769/article/details/76637890

微信APP支付(IOS手机端+java后台)版

0.介绍预览

针对需要在IOS手机上接入原生微信支付场景,调用微信进行支付。如图:

         

1.资料准备

1.1 账号注册

打开https://open.weixin.qq.com,注册微信开放平台开发者账号

1.2 开发者认证

登录,进入账号中心,进行开发者资质认证。

 

1.3 注册应用

认证完成后,进入管理中心,新建移动应用。填写应用资料,其中android版应用签名可通过扫码安装温馨提供的应用获得,详细参考微信文档。创建完成后点击查看,申请开通微信支付。一切准备就绪!

 

 

 


2.Java后台开发

添加依赖

[html]  view plain  copy
 print ?
  1. <!-- 微信支付依赖 -->  
  2. <dependency>  
  3.     <groupId>org.xmlpull</groupId>  
  4.     <artifactId>xmlpull</artifactId>  
  5.     <version>1.1.3.1 </version>  
  6. </dependency>  
  7. <dependency>  
  8.     <groupId>net.sf.json-lib</groupId>  
  9.     <artifactId>json-lib</artifactId>  
  10.     <version>2.3</version>  
  11.     <classifier>jdk15</classifier>  
  12. </dependency>  
  13. <!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->  
  14. <dependency>  
  15.     <groupId>com.thoughtworks.xstream</groupId>  
  16.     <artifactId>xstream</artifactId>  
  17.     <version>1.4.5</version>  
  18. </dependency>  
  19. <!-- https://mvnrepository.com/artifact/com.ning/async-http-client -->  
  20. <dependency>  
  21.     <groupId>com.ning</groupId>  
  22.     <artifactId>async-http-client</artifactId>  
  23.     <version>1.8.13</version>  
  24. </dependency>  


 

生成统一订单

[java]  view plain  copy
 print ?
  1.    @RequestMapping(value="/pay/wxpay/params",produces="application/json;charset=utf-8")  
  2.     @ResponseBody  
  3.     public String signprams(HttpServletRequest request){  
  4.         String res = "{code:404}";  
  5.         try{  
  6.         // 充值金额  
  7.             String account = request.getParameter("account");  
  8.         // 用户id  
  9.             String sid = request.getParameter("sid");  
  10.             String subject = "订单标题";  
  11.             String body = "订单描述";  
  12.   
  13.             int acc = (int) (Double.valueOf(account) * 100);  
  14.             String appid = "您的APPID";  
  15.             String out_trade_no = "生成您的订单号";  
  16.         // 生成订单数据  
  17.             SortedMap<String, String> payMap = genOrderData(request, subject, body, acc, appid, out_trade_no);  
  18.   
  19.             savePayLog(out_trade_no,account,sid,body,payMap.get("paySign"),nid,2);  
  20.   
  21.             // 4.返回数据  
  22.             res = buildPayRes(payMap,out_trade_no);  
  23.         }catch (Exception e){  
  24.             e.printStackTrace();  
  25.             res = "{code:500}";  
  26.         }  
  27.         return res;  
  28.     }  
  29.   
  30.     private SortedMap<String, String> genOrderData(HttpServletRequest request, String subject, String body,  
  31.                                        int acc, String appid, String out_trade_no)  
  32.             throws IOException, ExecutionException, InterruptedException, XmlPullParserException {  
  33.         SortedMap<String, String> paraMap = new TreeMap<String, String>();  
  34.         paraMap.put("appid", appid);  
  35.         paraMap.put("attach", subject);  
  36.         paraMap.put("body", body);  
  37.         paraMap.put("mch_id""您的商户id,到商户平台查看");  
  38.         paraMap.put("nonce_str", create_nonce_str());  
  39.         paraMap.put("notify_url""http://pay.xxxxx.com/pay/wxpay/notify.htm ");// 此路径是微信服务器调用支付结果通知路径  
  40.         paraMap.put("out_trade_no", out_trade_no);  
  41.         paraMap.put("spbill_create_ip", request.getRemoteAddr());  
  42.         paraMap.put("total_fee", acc+"");  
  43.         paraMap.put("trade_type""APP");  
  44.         String sign = createSign(paraMap);  
  45.         paraMap.put("sign", sign);  
  46.         // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder   
  47.         String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";  
  48.         String xml = getRequestXml(paraMap);  
  49.         String xmlStr = HttpKit.post(url, xml);  
  50.   
  51.         // 预付商品id  
  52.         String prepay_id = "";  
  53.         if (xmlStr.indexOf("SUCCESS") != -1) {  
  54.             Map<String, String> map = WXRequestUtil.doXMLParse(xmlStr);  
  55.             prepay_id = (String) map.get("prepay_id");  
  56.         }  
  57.   
  58.         SortedMap<String, String> payMap = new TreeMap<String, String>();  
  59.         payMap.put("appid", appid);  
  60.         payMap.put("partnerid""您的商户id,到商户平台查看");  
  61.         payMap.put("prepayid", prepay_id);  
  62.         payMap.put("package""Sign=WXPay");  
  63.         payMap.put("noncestr", create_nonce_str());  
  64.         payMap.put("timestamp", WXRequestUtil.create_timestamp());  
  65.         String paySign = createSign(payMap);  
  66.         payMap.put("paySign", paySign);  
  67.         return payMap;  
  68.     }  
  69.   
  70.     //请求xml组装    
  71.     public static String getRequestXml(SortedMap<String,String> parameters){    
  72.         String sign = "";  
  73.           StringBuffer sb = new StringBuffer();    
  74.           sb.append("<xml>");    
  75.           Set es = parameters.entrySet();    
  76.           Iterator it = es.iterator();    
  77.           while(it.hasNext()) {    
  78.               Map.Entry entry = (Map.Entry)it.next();    
  79.               String key = (String)entry.getKey();    
  80.               String value = (String)entry.getValue();    
  81. //              if ("attach".equalsIgnoreCase(key)||"body".equalsIgnoreCase(key)||"sign".equalsIgnoreCase(key)) {    
  82. //                  sb.append("<"+key+">"+value+"</"+key+">");    
  83. //              }  
  84.               if ("sign".equalsIgnoreCase(key)){  
  85.                   sign = "<"+key+">"+value+"</"+key+">";  
  86.               }else {    
  87.                   sb.append("<"+key+">"+value+"</"+key+">");    
  88.               }    
  89.           }    
  90.           sb.append(sign);    
  91.           sb.append("</xml>");    
  92.           return sb.toString();    
  93.       }   
  94.   
  95.     //生成签名    
  96.     public String createSign(SortedMap<String,String> parameters){    
  97.           StringBuffer sb = new StringBuffer();    
  98.           Set es = parameters.entrySet();    
  99.           Iterator it = es.iterator();    
  100.           while(it.hasNext()) {    
  101.               Map.Entry entry = (Map.Entry)it.next();    
  102.               String k = (String)entry.getKey();    
  103.               Object v = entry.getValue();    
  104.               if(null != v && !"".equals(v)    
  105.                       && !"sign".equals(k) && !"key".equals(k)) {    
  106.                   sb.append(k + "=" + v + "&");    
  107.               }    
  108.           }    
  109.           sb.append("key=" + WXConfig.APP_PERTNER_KEY);    
  110.           System.out.println(sb.toString());  
  111.           String sign = MD5Utils.MD5Encode(sb.toString(),"UTF-8").toUpperCase();    
  112.           return sign;    
  113.       }   
  114.   
  115.   
  116.     public String create_nonce_str() {  
  117.         String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
  118.         String res = "";  
  119.         for (int i = 0; i < 32; i++) {  
  120.             Random rd = new Random();  
  121.             res += chars.charAt(rd.nextInt(chars.length() - 1));  
  122.         }  
  123.         return res;  
  124.     }  


 

3.IOS客户端开发

导入微信开发包

 

添加URL Types

 

AppDelegate.m中注册应用

[objc]  view plain  copy
 print ?
  1. #import "AppDelegate.h"  
  2. #import "XSTabBarViewController.h"  
  3. #import <AlipaySDK/AlipaySDK.h>  
  4. #import "WXApi.h"  
  5.   
  6. @interface AppDelegate ()<WXApiDelegate>  
  7.   
  8. @end  
  9.   
  10. @implementation AppDelegate  
  11.   
  12.   
  13. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
  14.     // Override point for customization after application launch.  
  15.       
  16. //    [NSThread sleepForTimeInterval:2.0];  
  17.       
  18.     // 进入主控制器  
  19.     self.window = [[UIWindow alloc] init];  
  20.     self.window.frame = [UIScreen mainScreen].bounds;  
  21.     self.window.rootViewController = [[XSTabBarViewController alloc] init];  
  22.       
  23.     [self.window makeKeyAndVisible];  
  24.       
  25.     //向微信注册应用。  
  26.     [WXApi registerApp:@"wxfb96c2a9b531be26"];  
  27.       
  28.     return YES;  
  29. }  
  30.   
  31. -(void) onResp:(BaseResp*)resp  
  32. {  
  33. //        NSLog(@" ----onResp %@",resp);  
  34.     /* 
  35.      ErrCode ERR_OK = 0(用户同意) 
  36.      ERR_AUTH_DENIED = -4(用户拒绝授权) 
  37.      ERR_USER_CANCEL = -2(用户取消) 
  38.      code    用户换取access_token的code,仅在ErrCode为0时有效 
  39.      state   第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传,state字符串长度不能超过1K 
  40.      lang    微信客户端当前语言 
  41.      country 微信用户当前国家信息 
  42.      */  
  43.     if ([resp isKindOfClass:[SendAuthResp class]]) //判断是否为授权请求,否则与微信支付等功能发生冲突  
  44.     {  
  45.         SendAuthResp *aresp = (SendAuthResp *)resp;  
  46.         if (aresp.errCode== 0)  
  47.         {  
  48.             //            NSLog(@"code %@",aresp.code);  
  49.             [[NSNotificationCenter defaultCenter] postNotificationName:@"wechatDidLoginNotification" object:self userInfo:@{@"code":aresp.code}];  
  50.         }  
  51.     }else{  // 支付请求回调  
  52.         //支付返回结果,实际支付结果需要去微信服务器端查询  
  53.         NSString *strMsg = [NSString stringWithFormat:@"支付结果"];  
  54.         NSString *respcode = @"0";  
  55.         switch (resp.errCode) {  
  56.             case WXSuccess:  
  57.                 strMsg = @"支付结果:成功!";  
  58.                 //                NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);  
  59.                 respcode = @"1";  
  60.                 break;  
  61.             default:  
  62.                 strMsg = [NSString stringWithFormat:@"支付结果:失败!retcode = %d, retstr = %@", resp.errCode,resp.errStr];  
  63.                 //                NSLog(@"错误,retcode = %d, retstr = %@", resp.errCode,resp.errStr);  
  64.                 respcode = @"0";  
  65.                 break;  
  66.         }  
  67.         [[NSNotificationCenter defaultCenter] postNotificationName:@"wechatDidPayNotification" object:self userInfo:@{@"respcode":respcode}];  
  68.     }  
  69. }  
  70.   
  71.   
  72. //iOS 9.0 之前的处理方法不保证正确,如有错误还望指正  
  73. - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation  
  74. {  
  75.     NSLog(@"iOS 9.0 之前");  
  76.     return [self applicationOpenURL:url];  
  77. }  
  78.   
  79. -(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {  
  80.     NSLog(@"iOS 9.0 之后");  
  81.     return [self applicationOpenURL:url];  
  82. }  
  83.   
  84. - (BOOL)applicationOpenURL:(NSURL *)url  
  85. {  
  86.     if([[url absoluteString] rangeOfString:@"wxfb96c2a9b531be26://pay"].location == 0){  
  87.         return [WXApi handleOpenURL:url delegate:self];  
  88.     }  
  89.     if ([url.host isEqualToString:@"safepay"])  
  90.     {  
  91.         [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:nil];  
  92.         return YES;  
  93.     }  
  94.     return YES;  
  95. }  
  96.   
  97. }  



在需要支付的Controller中接受微信支付通知

[objc]  view plain  copy
 print ?
  1. - (void)viewDidLoad {  
  2.     [super viewDidLoad];  
  3.       
  4.     // 接受微信支付通知  
  5.     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wechatDidPayNotification:) name:@"wechatDidPayNotification" object:nil];  
  6. }  


 

向服务器端获取统一订单,并拉起微信进行支付

[objc]  view plain  copy
 print ?
  1. -(void)weixinPay  
  2. {  
  3.     NSString *userUrlStr = [NSString stringWithFormat:@"%@?sid=%@&account=%@&desc=%@", WX_PREPAY_URL, self.student.sid,self.payJinE,self.student.nid];  
  4.     NSURL *url = [NSURL URLWithString:userUrlStr];  
  5. //     NSLog(@"userUrlStr = %@", userUrlStr);  
  6.       
  7.     NSURLRequest *request = [NSURLRequest requestWithURL:url];  
  8.     AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request];  
  9.       
  10.     [MBProgressHUD showMessage:@"跳转中,请稍候"];  
  11.     [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, NSDictionary *responseObject) {  
  12.         [MBProgressHUD hideHUD];  
  13.           
  14. //         NSLog(@"微信支付的response = %@", operation.responseString);  
  15.         NSData *JSONData = [operation.responseString dataUsingEncoding:NSUTF8StringEncoding];  
  16.         NSDictionary *userDict = [NSJSONSerialization JSONObjectWithData:JSONData options:NSJSONReadingMutableLeaves error:nil];  
  17.           
  18.         // 调用微信支付  
  19.         PayReq *request = [[PayReq alloc] init];  
  20.         /** 商家向财付通申请的商家id */  
  21.         request.partnerId = [userDict objectForKey:@"partnerid"];  
  22.         /** 预支付订单 */  
  23.         request.prepayId= [userDict objectForKey:@"prepayid"];  
  24.         /** 商家根据财付通文档填写的数据和签名 */  
  25.         request.package = [userDict objectForKey:@"package"];  
  26.         /** 随机串,防重发 */  
  27.         request.nonceStr= [userDict objectForKey:@"noncestr"];  
  28.         /** 时间戳,防重发 */  
  29.         request.timeStamp= [[userDict objectForKey:@"timestamp"] intValue];  
  30.         /** 商家根据微信开放平台文档对数据做的签名 */  
  31.         request.sign= [userDict objectForKey:@"sign"];  
  32.         self.sign = request.sign;  
  33.         self.ordnum = [userDict objectForKey:@"ordnum"];  
  34.           
  35.   
  36.         [WXApi sendReq: request];  
  37.     }failure:^(AFHTTPRequestOperation *operation, NSError *error) {  
  38.         [MBProgressHUD hideHUD];  
  39.         NSLog(@"发生错误!%@",error);  
  40.     }];  
  41.     NSOperationQueue *queue = [[NSOperationQueue alloc] init];  
  42.     [queue addOperation:operation];  
  43.       
  44. }  
  45. // 微信支付结果  
  46. -(void)wechatDidPayNotification:(NSNotification *)notification  
  47. {  
  48. //    NSLog(@"wechatDidPayNotification");  
  49.     NSDictionary *nameDictionary = [notification userInfo];  
  50.     NSString *respcode = [nameDictionary objectForKey:@"respcode"];  
  51.     if([respcode isEqualToString:@"1"]){  
  52.         // 支付成功,更新用户信息  
  53.         [self payDidFinish];  
  54.     }else{  
  55.         // 支付失败,  
  56.         [self setupAlertControllerWithTitle:@"微信支付结果" messge:@"本次支付未完成,您可以稍后重试!" confirm:@"好的"];  
  57.     }  
  58. }  


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值