iOS-不同应用使用同一个微信支付
2017-07-21 本文已影响353人
elite_kai
之前我写过一篇关于微信支付的文章
http://www.jianshu.com/p/259b9285dae0
这篇文章是大家常用的方法,一般都是一个appid对应一个应用。
接下来我们解决一个appid对应不同应用的场景。
一个appid对应不同应用的时候会有一个问题,在微信中点击返回的时候,无法返回app,你可以通过点击左上角返回或者从后台重新进入到应用
直接看代码
在Applegate中代码如下
#import "AppDelegate.h"
//微信支付
#import "WXApi.h"
@interface AppDelegate ()<WXApiDelegate>
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//注册微信支付
[WXApi registerApp:APP_id withDescription:@"demo"];
return YES;
}
//iOS9 之后使用这个回调方法。
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
{
if ([url.host isEqualToString:@"pay"]) {
return [WXApi handleOpenURL:url delegate:self];
}
return YES;
}
#pragma mark - 微信支付的代理方法
- (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
{
if ([url.host isEqualToString:@"pay"]) {
return [WXApi handleOpenURL:url delegate:self];
}
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"wxPayNotification" object:nil];
}
上面有两个系统回调的方法,第一个是针对ios9.0以后,第二个是针对ios9.0之前的
在带有微信支付的页面我们做如下处理
#import "ViewController.h"
//微信支付
#import "WXApi.h"
#import "payRequsestHandler.h"
#import "WXUtil.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(60, 100, 180, 100)];
button.backgroundColor = [UIColor redColor];
[button setTitle:@"微信支付" forState:UIControlStateNormal];
[button addTarget:self action:@selector(test) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
//接受成功的通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(succeed) name:@"wxPayNotification" object:nil];
}
#pragma mark - ASction Methods
- (void)test
{
payRequsestHandler *handle = [[payRequsestHandler alloc]init];
if ( [handle init:APP_id mch_id:MCH_id]) {
NSLog(@"初始化成功");
}
//设置商户密钥
[handle setKey:PARTNER_id];
//提交预支付,获得prepape_id
NSString *order_name = @"测试"; //订单标题
NSString *order_price = @"1";//测试价格 分为单位
NSString *nocify_URL = nocify_url; //回调借口
NSString *noncestr = [NSString stringWithFormat:@"%d", rand()]; //随机串
NSString *orderno = [NSString stringWithFormat:@"%ld",time(0)];
NSMutableDictionary *params = [@{@"appid":APP_id,
@"mch_id":MCH_id,
@"device_info":[[[UIDevice currentDevice] identifierForVendor] UUIDString],
@"nonce_str":noncestr,
@"trade_type":@"APP",
@"body":order_name,
@"notify_url":nocify_URL,
@"out_trade_no":orderno,//商户订单号:这个必须用后台的订单号
@"spbill_create_ip":@"8.8.8.8",
@"total_fee":order_price}mutableCopy];
//提交预支付两次签名得到预支付订单的id(每次的请求得到的预支付订单id都不同)
NSString *prepate_id = [handle sendPrepay:params];
//提交预订单成功
if (prepate_id != nil) {
PayReq *request = [[PayReq alloc]init];
//商家id
request.partnerId = MCH_id;
//订单id
request.prepayId = prepate_id;
//扩展字段(官方文档:暂时填写固定值)
request.package = @"Sign=WXPay";
//随机字符串
request.nonceStr = noncestr;
//时间戳
request.timeStamp = (UInt32)[[NSDate date] timeIntervalSince1970];
//sign参数(很经常出现的问题:就是调起支付到微信那边只出现一个确定按钮,单击确认按钮直接返回到app,出现这个问题100%是sign参数的问题)
/*
参数依次是: appid_key、partnerid_key、prepayid_key、固定值Sign=WXPay、预支付的随机数(跟上面得到预支付订单的随机数要一致)、支付时间(秒)
*/
request.sign = [self createMD5SingForPay:APP_id partnerid:MCH_id prepayid:prepate_id package:@"Sign=WXPay" noncestr:noncestr timestamp:(UInt32)[[NSDate date] timeIntervalSince1970]];
//生成URLscheme
NSString *str = [NSString stringWithFormat:@"weixin://app/%@/pay/?nonceStr=%@&package=Sign%%3DWXPay&partnerId=%@&prepayId=%@&timeStamp=%@&sign=%@&signType=SHA1",APP_id,request.nonceStr,request.partnerId,request.prepayId,[NSString stringWithFormat:@"%d",request.timeStamp],request.sign];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:str]];
}
}//点击微信支付
#pragma mark - Private Methods
-(NSString *)createMD5SingForPay:(NSString *)appid_key partnerid:(NSString *)partnerid_key prepayid:(NSString *)prepayid_key package:(NSString *)package_key noncestr:(NSString *)noncestr_key timestamp:(UInt32)timestamp_key
{
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject:appid_key forKey:@"appid"];
[signParams setObject:noncestr_key forKey:@"noncestr"];
[signParams setObject:package_key forKey:@"package"];
[signParams setObject:partnerid_key forKey:@"partnerid"];
[signParams setObject:prepayid_key forKey:@"prepayid"];
[signParams setObject:[NSString stringWithFormat:@"%u",(unsigned int)timestamp_key] forKey:@"timestamp"];
NSMutableString *contentString =[NSMutableString string];
NSArray *keys = [signParams allKeys];
//按字母顺序排序
NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
//拼接字符串
for (NSString *categoryId in sortedArray) {
if ( ![[signParams objectForKey:categoryId] isEqualToString:@""]
&& ![[signParams objectForKey:categoryId] isEqualToString:@"sign"]
&& ![[signParams objectForKey:categoryId] isEqualToString:@"key"]
)
{
[contentString appendFormat:@"%@=%@&", categoryId, [signParams objectForKey:categoryId]];
}
}
//添加商户密钥key字段
[contentString appendFormat:@"key=%@",PARTNER_id];
NSString *result = [self md5:contentString];
return result;
}//创建发起支付时的sige签名
-(NSString *)md5:(NSString *)str
{
const char *cStr = [str UTF8String];
unsigned char result[16]= "0123456789abcdef";
CC_MD5(cStr, (CC_LONG)strlen(cStr), result);
//这里的x是小写则产生的md5也是小写,x是大写则md5是大写,这里只能用大写,微信的大小写验证很逗
return [NSString stringWithFormat:
@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]
];
}//MD5 加密
- (void)succeed
{
//在这里调用一个接口,让服务器端写一个查询订单的接口,然后返回订单的状态,成功或者失败,然后你就可以通过订单状态进行下一步操作
NSLog(@"支付成功");
}//支付成功的监听方法
#pragma mark - OverRide Methods
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"wxPayNotification" object:nil];
}//移除通知
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end