足球盘口软件
当前位置: 足球盘口软件 > 前端 >
Android集成微信支付,iOS开发集成微信支付

iOS集成微信支付的一些坑(onResp不回调、闪回等)

iOS集成微信支付总体来说还是比较容易的(如果没有那些坑的话),所有文档都在:

 

甚至只要看:

这两部分就可以搞定。

遇到的大部分问题来自于另一个非常常用的第三方:友盟分享

 

关于

已经集成了友盟分享

只要下载微信sdk,并复制到友盟目录下的UMSocial_Sdk_Extra_Frameworks/Wechat文件夹中,替换存在文件。

 

 

关于

发起支付之后只显示一个确定按钮

图片 1

 

就是这样,没有任何错误提示,断点返回的UrlSchemes,也只有一个ret=-2,官方文档解释为:

“无需处理。发生场景:用户不支付了,点击取消,返回APP。”

 

遇到这个问题,基本就是发起请求的参数传错了。

 

PayReq *request = [[[PayReq alloc] init] autorelease];
request.partnerId = @"10000100";
request.prepayId= @"1101000000140415649af9fc314aa427";
request.package = @"Sign=WXPay";
request.nonceStr= @"a462b76e7436e98e0ed6e13c64b4fd1c";
request.timeStamp= @"1397527777";
request.sign= @"582282D72DD2B03AD892830965F428CB16E7A256";
[WXApi sendReq:request];

 

 

对照文档仔细排查吧,一定要注意大小写,另外,sign签名时,参数名要用小些(此处官方文档有错误,文档写的用驼峰那种: 步骤3-参与签名的字段名,此处感谢 @挨踢实习生) 。

 

关于

闪回

 

发起支付后,打开微信,然后立即返回到了你的程序。

原因是项目同时集成了友盟,注册微信的方法写在了初始化友盟分享的前面,调换一下位置即可。

 

//向微信注册,需要写到初始化友盟分享的后面
[WXApi registerApp:@"wx000000000" withDescription:@"**weixinpay"];  //你的微信appid

 

 

 

关于

onResp不回调

 

这个问题依然来自跟友盟分享的冲突。虽然友盟提供了一个

 

+(BOOL)handleOpenURL:(NSURL *)url wxApiDelegate:(id)wxApiDelegate;

 

方法,但是通过此方法注册的delegate并没有被回调(这个有可能在不同系统版本,友盟sdk版本上效果不同)。

 

 

解决方法就是判断一下回调是不是微信支付:

 

//url Schemes回调
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
    return [self applicationOpenURL:url];
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    return [self applicationOpenURL:url];
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options
{
    return [self applicationOpenURL:url];
}

- (BOOL)applicationOpenURL:(NSURL *)url
{
    if([[url absoluteString] rangeOfString:@"wx000000000000://pay"].location == 0) //你的微信开发者appid
        return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
    else
        return [UMSocialSnsService handleOpenURL:url wxApiDelegate:[WXApiManager sharedManager]];
}

 

 

 

iOS集成微信支付总体来说还是比较容易的(如果没有那些坑的话),所有文档都在: https:/...

之前做过微信支付,也遇到了一些坑,只是当时没有总结。再次使用时还要看开发文档,重新踩坑,所以有必要总结一下,为了下次快速集成。
微信官方集成文档
支付开发者文档

照着官网写好了 支付直接报败,挫败~~~

首先需要理清楚流程:

1、用户使用APP客户端,选择商品下单。

2、商户客户端(就是你做的APP)将用户的商品数据传给商户服务器,请求生成支付订单。

3、商户后台调用统一下单API向微信的服务器发送请求,微信服务器生成预付单,并生成一个prepay_id返回给商户后台。

4、商户后台将这个prepay_id返回给商户客户端。

5、用户点击确认支付,这时候商户客户端调用SDK打开微信客户端,进行微信支付。

6、微信客户端向微信服务器发起支付请求并返回支付结果(他们之间交互用的就是prepay_id这个参数,微信的服务器要验证微信客户端传过去的参数是否跟第三步中生成的那个id一致)。

7、用户输入支付密码后,微信客户端提交支付授权,跟微信服务器交互,完成支付。

8、微信服务器给微信客户端发送支付结果提示,并异步给商户服务器发送支付结果通知。

9、商户客户端通过支付结果回调接口查询支付结果,并向后台检查支付结果是否正确,后台返回支付结果。

10、商户客户端显示支付结果,完成订单,发货。

虽然看起来有点多,但是理解起来并不复杂,跟我们平时手机上买东西是一样的。我们客户端需要做的就是:

     1.调起微信客户端发起支付

     2.显示支付结果

1.Android studio微信支付sdk可以通过gradle来导入

  dependencies {
          compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
}

先把官方demo下载下来,可以本地倒入sdk,我是适用的pods,因为之前已经集成了分享功能,已经有微信的sdk了,所以我只需要倒入XMLDictionary、DataMD5这俩工具类到我的项目,这个我放本地了,还有一点需要注意的是,集成过微信之后,做支付的时候,注册微信注意放到分享之后!!

集成过程

首先是要下载SDK

图片 2

2.接收微信的请求及返回值(坑点)

集成文档是这样描述的

图片 3

Paste_Image.png

看图是并列关系,但是并非如此,应该如此

图片 4

Paste_Image.png

我的didFinishLaunchingWithOptions方法里这样写的:

导入微信支付SDK库

导入上面那个iOS头文件和库下载下载出来的SDK包的就行啦,我这里的是SDK1.6.2. 然后需要链接上依赖库,在Target —> BuildPhases —> Link Binary With Libraries— 点击+号 -> 搜索你需要的系统库。

3..调起微信APP进行支付

调起支付需要传递参数,需要请求自己服务器返回如下参数:

图片 5

Paste_Image.png

返回参数后,调起微信

  //微信支付api
  private IWXAPI iwxapi;
     /**
        *调起微信支付的方法
        **/
 private void toWXPay() {
 //初始化微信api
    iwxapi = WXAPIFactory.createWXAPI(this, null);
 //注册appid  appid可以在开发平台获取
    iwxapi.registerApp(appid); 

    Runnable payRunnable = new Runnable() {  //这里注意要放在子线程
        @Override
        public void run() {
            PayReq request = new PayReq(); //调起微信APP的对象
            //下面是设置必要的参数,也就是前面说的参数,这几个参数从何而来请看上面说明
            request.appId = appid;
            request.partnerId = partnerId;
            request.prepayId = prepayId;
            request.packageValue = "Sign=WXPay";
            request.nonceStr = nonceStr;
            request.timeStamp = timeStamp;
            request.sign = sign;
            iwxapi.sendReq(request);//发送调起微信的请求
        }
    };
    Thread payThread = new Thread(payRunnable);
    payThread.start();
}

签名sign 参数,又时需要我们客户端来生成,来看一下生成规则

图片 6

Paste_Image.png

生成事例:

               //签名
            LinkedHashMap<String, String> signParams = new LinkedHashMap<>();
            signParams.put("appid", request.appId);
            signParams.put("noncestr", request.nonceStr);
            signParams.put("package", request.packageValue);
            signParams.put("partnerid", request.partnerId);
            signParams.put("prepayid", request.prepayId);
            signParams.put("timestamp", request.timeStamp);
            request.sign = genPackageSign(signParams,key);
            iwxapi.sendReq(request);//发送调起微信的请求
 /**
 * 调起微信APP支付,签名
 * 生成签名
 */
private   String genPackageSign(LinkedHashMap<String, String> params,String key) {
    StringBuilder sb = new StringBuilder();
    for (Map.Entry<String,String> entry: params.entrySet()) {
        sb.append(entry.getKey());
        sb.append('=');
        sb.append(entry.getValue());
        sb.append('&');
    }
    sb.append("key=");
    sb.append(key);

    String packageSign = getMessageDigest(sb.toString().getBytes()).toUpperCase();
    return packageSign;
}

/**
 * md5加密
 * @param buffer
 * @return
 */
private String getMessageDigest(byte[] buffer) {
    char hexDigits[] = { 'a', 'b', 'c', 'd', 'e', 'f' , 'g', 'h', 'l', 'm', 'n', 'o' };
    try {
        MessageDigest mdTemp = MessageDigest.getInstance("MD5");
        mdTemp.update(buffer);
        byte[] md = mdTemp.digest();
        int j = md.length;
        char str[] = new char[j * 2];
        int k = 0;
        for (int i = 0; i < j; i++) {
            byte byte0 = md[i];
            str[k++] = hexDigits[byte0 >>> 4 & 0xf];
            str[k++] = hexDigits[byte0 & 0xf];
        }
        return new String(str);
    } catch (Exception e) {
        return null;
    }
}
/**
 * 获取随机数
 *
 * @return
 */
private String genNonceStr() {
    Random random = new Random();
    return getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}


/**
 * 获取时间戳
 *
 * @return
 */
private long genTimeStamp() {
    return System.currentTimeMillis() / 1000;
}

- (void)registerApp {

SystemConfiguration.framework

4.微信支付的回调

处理微信支付的回调就是在创建的WXEntryActivity中处理。需要实现IWXAPIEventHandler接口,这个接口会要求你实现onResp方法,就在这个方法中处理回调。

 @Override
  public void onResp(BaseResp resp) {

    if(resp.getType()==ConstantsAPI.COMMAND_PAY_BY_WX){
        if(resp.errCode==0){
            Toast.makeText(this, "支付成功", Toast.LENGTH_LONG).show();
        }
        else {
            Toast.makeText(this, "支付失败", Toast.LENGTH_LONG).show();
        }
        finish();
    }
}

//打开日志

libz.tbd

[[UMSocialManager defaultManager] openLog:YES];

libsqlite3.0.tbd

// 获取友盟social版本号

CoreTelephony.framework

NSLog(@"UMeng social version: %@", [UMSocialGlobal umSocialSDKVersion]);

QuartzCore.framework

//设置友盟appkey

设置URL Scheme

在注册微信平台APP的时候,会给一个唯一识别标识符(APPID),在APP端开发步骤里面说得很清楚了,需要填在URL Schemes这个地方

图片 7

[[UMSocialManager defaultManager] setUmSocialAppkey:UmSocialAppkey];

在Appdelegate中注册APPID

如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// Override point for customization after application launch.

/**

*  向微信终端注册ID,这里的APPID一般建议写成宏,容易维护。@“测试demo”不需用管。这里的id是假的,需要改这里还有target里面的URL Type

*/

[WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"测试demo"];

return YES;

}

处理微信通过URL启动时传递的数据//前面的两个方法被iOS9弃用了,如果是Xcode7.2网上的话会出现无法进入进入微信的onResp回调方法,就是这个原因。本来我是不想写着两个旧方法的,但是一看官方的DEMO上写的这两个,我就也写了。。。

//9.0前的方法,为了适配低版本 保留

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{    return [WXApi handleOpenURL:url delegate:self];

}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{    return [WXApi handleOpenURL:url delegate:self];

}

//9.0后的方法

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options{

//这里判断是否发起的请求为微信支付,如果是的话,用WXApi的方法调起微信客户端的支付页面(://pay 之前的那串字符串就是你的APPID,)

return  [WXApi handleOpenURL:url delegate:self];

}

//微信SDK自带的方法,处理从微信客户端完成操作后返回程序之后的回调方法,显示支付结果的

-(void) onResp:(BaseResp*)resp

{

       //启动微信支付的response

       NSString *payResoult = [NSString stringWithFormat:@errcode:%d, resp.errCode];

       if([resp isKindOfClass:[PayResp class]]){

       //支付返回结果,实际支付结果需要去微信服务器端查询

       switch (resp.errCode) {

       case 0:

       payResoult = @支付结果:成功!;

       break;

       case -1:

       payResoult = @支付结果:失败!;

       break;

       case -2:

       payResoult = @用户已经退出支付!;

       break;

      default:

      payResoult = [NSString stringWithFormat:@支付结果:失败!retcode = %d, retstr =            %@, resp.errCode,resp.errStr]; 

      break;

    }

  } 

}

//设置微信的appKey和appSecret

最重要的来了!

调用微信支付前,需要下单、签名等操作,以便获取微信支付所必要的参数。为了提高安全性,下单、签名操作一般是在后台完成,在前台做的话被捕获改信息就不开心了。。。

需要的参数包括:appid、partid(商户号)、prepayid(预支付订单ID)、noncestr(参与签名的随机字符串)、timestamp(参与签名的时间戳)、sign(签名字符串)这六个。

在点击支付的控制器中使用核心代码来调起微信客户端支付,这些个参数都是后台传给你的。 加上了注释,应该很好理解的。

[[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_WechatSession appKey:WeiXinAppKey appSecret:WeiXinAppSecret redirectURL:@"];

#pragma mark 微信支付方法

- (void)WXPay{

//需要创建这个支付对象

PayReq *req  = [[PayReq alloc] init];

//由用户微信号和AppID组成的唯一标识,用于校验微信用户

req.openID = @"";

// 商家id,在注册的时候给的

req.partnerId = @"";

// 预支付订单这个是后台跟微信服务器交互后,微信服务器传给你们服务器的,你们服务器再传给你

req.prepayId  = @"";

// 根据财付通文档填写的数据和签名

//这个比较特殊,是固定的,只能是即req.package = Sign=WXPay

req.package  = @"";

// 随机编码,为了防止重复的,在后台生成

req.nonceStr  = @"";

// 这个是时间戳,也是在后台生成的,为了验证支付的

NSString * stamp = @"";

req.timeStamp = stamp.intValue;

// 这个签名也是后台做的

req.sign = @"";

//发送请求到微信,等待微信返回onResp

[WXApi sendReq:req];

}

这个JSON里面的数据(上面的参数)就是后台需要传给你的,至于怎么来,也有后台的文档,让他去看下就行啦~~~

{

"appid": "wxb4ba3c02aa476ea1",

"noncestr": "d1e6ecd5993ad2d06a9f50da607c971c",

"package": "Sign=WXPay",

"partnerid": "10000100",

"prepayid": "wx20160218122935e3753eda1f0066087993",

"timestamp": "1455769775",

"sign": "F6DEE4ADD82217782919A1696500AF06"

}

//设置分享到QQappID

统一下单API

[[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_QQ appKey:QQAppKey/*设置QQ平台的appID*/  appSecret:QQAppSecret redirectURL:@"];

调起支付接口

到这里,不出意外的话应该都能正常的支付了。流程最重要,理解了就知道怎么做了,强烈建议需要做的朋友们先理理思路,不要急着下手。

PS:这篇文章中,签名都是在后台做的,如果需要在你的客户端做,可以参考下这篇文章iOS 集成微信支付 - 微信公众平台开发:微信公众号开发平台教程,技术文摘 - 红黑联盟(

  • iPhone手机开发技术文章 - 红黑联盟](

//微博的appKey

可能遇到的问题:

1、如果支付完成后,一直留在微信,那就检查下URLType中的Scheme设置问题。

2、能够打开微信客户端,但是打开后只有中间一个白色的 “确定按钮”,点击后会回到客户端上,如果是这样,那应该是prepayid 参数的问题,过期了,或者不是真实的id。代码没有问题的。特别注意的是,微信要两次签名,两次~~~~

3、如果APP里面使用了友盟或者ShareSDK做分享,那就不用再导入SDK了,否则会出现一些诡异的问题,例如无法调起手机微信客户端、无法调起微信客户端web页面,调起了但是一闪而过。。。这都基本上都是因为分享的SDK里面已经包括了微信的SDK。所以如果出现诡异的错误了看看是不是两个冲突了!

4、微信支付的单位是分,被坑过的人都知道了。。。哎!

如果在集成过程中遇到什么问题,大家可以一起讨论下,我记录这些如果有什么错误的话也请告诉我!谢谢! 

[[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_Sina appKey:WeiBoAppKey appSecret:WeiBoAppSecret redirectURL:@"];

// 微信支付 有分享的时候 注册放在分享后面

[WXApi registerApp:WeiXinAppKey];

}

具体的介绍看官方和百度,我这里记录一下自己出问题的地方:

1、下单、签名操在后台完成:

需要的参数包括:appid、partid(商户号)、prepayid(预支付订单ID)、noncestr(参与签名的随机字符串)、timestamp(参与签名的时间戳)、sign(签名字符串)这六个大概;

2、客户端拿着这些参数掉起支付:

//需要创建这个支付对象

PayReq *req = [[PayReq alloc] init];

//由用户微信号和AppID组成的唯一标识,用于校验微信用户

req.openID = WeiXinAppKey;

// 商家id,在注册的时候给的

req.partnerId = orderInfo[@"mch_id"];

// 预支付订单这个是后台跟微信服务器交互后,微信服务器传给你们服务器的,你们服务器再传给你

req.prepayId  = orderInfo[@"prepay_id"];

// 根据财付通文档填写的数据和签名

//这个比较特殊,是固定的,只能是即req.package = Sign=WXPay

req.package  = @"Sign=WXPay";

// 随机编码,为了防止重复的,在后台生成

req.nonceStr  = orderInfo[@"nonce_str"];

// 这个是时间戳,也是在后台生成的,为了验证支付的

//将当前事件转化成时间戳

NSDate *datenow = [NSDate date];

NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];

UInt32 timeStamp =[timeSp intValue];

req.timeStamp= timeStamp;

// 签名加密

DataMD5 *md5 = [[DataMD5 alloc] init];

req.sign=[md5 createMD5SingForPay:req.openID partnerid:req.partnerId prepayid:req.prepayId package:req.package noncestr:req.nonceStr timestamp:req.timeStamp];

//发送请求到微信,等待微信返回onResp

BOOL status = [WXApi sendReq:req];

3、得到支付结果,在AppDelegate.m文件里吗写回调的通知:

//微信SDK自带的方法,处理从微信客户端完成操作后返回程序之后的回调方法,显示支付结果的

-(void)onResp:(BaseResp*)resp

{

//启动微信支付的response

if([resp isKindOfClass:[PayResp class]]){

[[NSNotificationCenter defaultCenter] postNotificationName:@"WXpayresult" object:[NSString stringWithFormat:@"%d",resp.errCode]];

}

}

在发起支付的地方监听到回掉消息做相应处理:

- (void)viewDidLoad {

[super viewDidLoad];

// 注册监听 - 微信支付结果

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showWXPayResult:) name:@"WXpayresult" object:nil];

}

- (void)viewDidDisappear:(BOOL)animated {

[super viewDidDisappear:animated];

[[NSNotificationCenter defaultCenter] removeObserver:self];

}

#pragma mark 微信支付的结果

- (void)showWXPayResult:(NSNotification *)notification {

NSString *result = notification.object;

//支付返回结果,实际支付结果需要去微信服务器端查询

NSString *payResoult = @"";

if (result.intValue == 0) {

payResoult = @"支付结果:成功!";

}else {

self.payResult = NO;

switch (result.intValue) {

case -1:

payResoult = @"支付结果:失败!";

break;

case -2:

payResoult = @"用户已经退出支付!";

break;

default:

payResoult = [NSString stringWithFormat:@"支付结果:失败!retcode = %d", result.intValue];

break;

}

UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"提示" message:payResoult delegate:nil cancelButtonTitle:@"好的" otherButtonTitles: nil];

[alert show];

}

}

返回顶部