- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章IOS客户端接入微信支付由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
实际上,从代码的角度,调起支付APP就是把一些关键的参数通过一定方式打包成为一个订单,然后发送到支付平台的服务器。所以,只要搞清楚了参数设置,搞清楚了每个支付平台的SDK里面一些关键API的使用,基本上就可以很简单的支持支付.
今天记录一下客户端里面,如何支持微信支付。首先。我们要仔细阅读一下微信SDK的开发文档,了解一下整个支付的大概流程.
然后根据提示,把相应的SDK下载下来,所谓的SDK,也就是一个链接库和两个头文件,很简单.
下载完毕,需要把SDK导入到工程里面,并且配置一下工程。因为开发者文档已经有详细描述,这里就不再复述.
从文档看到,调起微信支付其实最核心的是一下这么一段 。
1
2
3
4
5
6
7
8
|
<code
class
=
"hljs"
vbscript=
""
>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];</code>
|
这里的范例是一段hardcode,真正使用的时候,参数都需要自行传入.
为了搞清楚如何使用API,我们可以下载Sample代码。不过,这个sample代码应该是微信的实习生写的,而且应该是一个对于C++比较熟悉,对于ObjectC比较陌生的实习生。。。代码风格可以看出很多东西哈。。所以这个sample读起来总觉得有点奇怪。当然,写出这个demo也是需要不错的水平,因为这个sample不仅仅是一些API的调用,还包括了一些算法的实现,MD5之类的。 看懂了sample之后,一般可以自己重构一下,成为自己APP里面的一个Manager类.
我是在2015 5 23下载的微信Sampel代码,里面包括有:
ApiXml.h 。
ApiXml.m 。
WXUtil.h 。
WXUtil.m 。
payRequestHandler.h 。
payRequestHandler.m 。
如果比较看重命名规范的OC程序猿,就会觉得这个payRequestHandler类非常别扭,不符合camel命名规则,而且handler这个词更偏向于c++风格。我就以这个类为原型,重构了一下,并改装成一个传参的方法,供自己的APP调用。APP里面卖商品,一般就是商品名字,价格两个关键参数。所以这个重构的方法也只是提供这两个参数的接口。 ApiXml.h && ApiXml.m && WXUtil.h && WXUtil.m不变 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
|
<code
class
=
"hljs"
objectivec=
""
>
//
// WechatPayManager.h
//
// Created by HuangCharlie on 5/24/15.
//
//
#import <foundation foundation.h="">
#import WXUtil.h
#import ApiXml.h
#import WXApi.h
// 账号帐户资料
// 更改商户把相关参数后可测试
#define APP_ID @wx@@@@@@@@@@@@@@@@ //APPID
#define APP_SECRET @ //appsecret,看起来好像没用
//商户号,填写商户对应参数
#define MCH_ID @@@@@@@@@@@
//商户API密钥,填写相应参数
#define PARTNER_ID @12345678901234567890123456789012
//支付结果回调页面
#define NOTIFY_URL @http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php
//获取服务器端支付数据地址(商户自定义)(在小吉这里,签名算法直接放在APP端,故不需要自定义)
#define SP_URL @http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php
@
interface
WechatPayManager : NSObject
{
}
//预支付网关url地址
@property (nonatomic,strong) NSString* payUrl;
//debug信息
@property (nonatomic,strong) NSMutableString *debugInfo;
@property (nonatomic,assign) NSInteger lastErrCode;
//返回的错误码
//商户关键信息
@property (nonatomic,strong) NSString *appId,*mchId,*spKey;
//初始化函数
-(id)initWithAppID:(NSString*)appID
mchID:(NSString*)mchID
spKey:(NSString*)key;
//获取当前的debug信息
-(NSString *) getDebugInfo;
//获取预支付订单信息(核心是一个prepayID)
- (NSMutableDictionary*)getPrepayWithOrderName:(NSString*)name
price:(NSString*)price
device:(NSString*)device;
@end
</foundation></code>
<code
class
=
"hljs"
objectivec=
""
>
//
// WechatPayManager.m
//
// Created by HuangCharlie on 5/24/15.
//
//
#import WechatPayManager.h
@implementation WechatPayManager
//初始化函数
-(id)initWithAppID:(NSString*)appID mchID:(NSString*)mchID spKey:(NSString*)key
{
self = [super init];
if
(self)
{
//初始化私有参数,主要是一些和商户有关的参数
self.payUrl = @https:
//api.mch.weixin.qq.com/pay/unifiedorder;
if
(self.debugInfo == nil){
self.debugInfo = [NSMutableString
string
];
}
[self.debugInfo setString:@];
self.appId = appID;
//微信分配给商户的appID
self.mchId = mchID;
//
self.spKey = key;
//商户的密钥
}
return
self;
}
//获取debug信息
-(NSString*) getDebugInfo
{
NSString *res = [NSString stringWithString:self.debugInfo];
[self.debugInfo setString:@];
return
res;
}
//创建package签名
-(NSString*) createMd5Sign:(NSMutableDictionary*)dict
{
NSMutableString *contentString =[NSMutableString
string
];
NSArray *keys = [dict allKeys];
//按字母顺序排序
NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return
[obj1 compare:obj2 options:NSNumericSearch];
}];
//拼接字符串
for
(NSString *categoryId
in
sortedArray) {
if
( ![[dict objectForKey:categoryId] isEqualToString:@]
&& ![categoryId isEqualToString:@sign]
&& ![categoryId isEqualToString:@key]
)
{
[contentString appendFormat:@%@=%@&, categoryId, [dict objectForKey:categoryId]];
}
}
//添加key字段
[contentString appendFormat:@key=%@, self.spKey];
//得到MD5 sign签名
NSString *md5Sign =[WXUtil md5:contentString];
//输出Debug Info
[self.debugInfo appendFormat:@MD5签名字符串:
%@
,contentString];
return
md5Sign;
}
//获取package带参数的签名包
-(NSString *)genPackage:(NSMutableDictionary*)packageParams
{
NSString *sign;
NSMutableString *reqPars=[NSMutableString
string
];
//生成签名
sign = [self createMd5Sign:packageParams];
//生成xml的package
NSArray *keys = [packageParams allKeys];
[reqPars appendString:@<xml>
];
for
(NSString *categoryId
in
keys) {
[reqPars appendFormat:@<%@>%@<!--%@-->
, categoryId, [packageParams objectForKey:categoryId],categoryId];
}
[reqPars appendFormat:@<sign>%@</sign>
</xml>, sign];
return
[NSString stringWithString:reqPars];
}
//提交预支付
-(NSString *)sendPrepay:(NSMutableDictionary *)prePayParams
{
NSString *prepayid = nil;
//获取提交支付
NSString *send = [self genPackage:prePayParams];
//输出Debug Info
[self.debugInfo appendFormat:@API链接:%@
, self.payUrl];
[self.debugInfo appendFormat:@发送的xml:%@
, send];
//发送请求post xml数据
NSData *res = [WXUtil httpSend:self.payUrl method:@POST data:send];
//输出Debug Info
[self.debugInfo appendFormat:@服务器返回:
%@
,[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]];
XMLHelper *xml = [[XMLHelper alloc] autorelease];
//开始解析
[xml startParse:res];
NSMutableDictionary *resParams = [xml getDict];
//判断返回
NSString *return_code = [resParams objectForKey:@return_code];
NSString *result_code = [resParams objectForKey:@result_code];
if
( [return_code isEqualToString:@SUCCESS] )
{
//生成返回数据的签名
NSString *sign = [self createMd5Sign:resParams ];
NSString *send_sign =[resParams objectForKey:@sign] ;
//验证签名正确性
if
( [sign isEqualToString:send_sign]){
if
( [result_code isEqualToString:@SUCCESS]) {
//验证业务处理状态
prepayid = [resParams objectForKey:@prepay_id];
return_code = 0;
[self.debugInfo appendFormat:@获取预支付交易标示成功!
];
}
}
else
{
self.lastErrCode = 1;
[self.debugInfo appendFormat:@gen_sign=%@
_sign=%@
,sign,send_sign];
[self.debugInfo appendFormat:@服务器返回签名验证错误!!!
];
}
}
else
{
self.lastErrCode = 2;
[self.debugInfo appendFormat:@接口返回错误!!!
];
}
return
prepayid;
}
- (NSMutableDictionary*)getPrepayWithOrderName:(NSString*)name
price:(NSString*)price
device:(NSString*)device
{
//订单标题,展示给用户
NSString* orderName = name;
//订单金额,单位(分)
NSString* orderPrice = price;
//以分为单位的整数
//支付设备号或门店号
NSString* orderDevice = device;
//支付类型,固定为APP
NSString* orderType = @APP;
//发器支付的机器ip,暂时没有发现其作用
NSString* orderIP = @196.168.1.1;
//随机数串
srand( (unsigned)time(0) );
NSString *noncestr = [NSString stringWithFormat:@%d, rand()];
NSString *orderNO = [NSString stringWithFormat:@%ld,time(0)];
//================================
//预付单参数订单设置
//================================
NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
[packageParams setObject: self.appId forKey:@appid];
//开放平台appid
[packageParams setObject: self.mchId forKey:@mch_id];
//商户号
[packageParams setObject: orderDevice forKey:@device_info];
//支付设备号或门店号
[packageParams setObject: noncestr forKey:@nonce_str];
//随机串
[packageParams setObject: orderType forKey:@trade_type];
//支付类型,固定为APP
[packageParams setObject: orderName forKey:@body];
//订单描述,展示给用户
[packageParams setObject: NOTIFY_URL forKey:@notify_url];
//支付结果异步通知
[packageParams setObject: orderNO forKey:@out_trade_no];
//商户订单号
[packageParams setObject: orderIP forKey:@spbill_create_ip];
//发器支付的机器ip
[packageParams setObject: orderPrice forKey:@total_fee];
//订单金额,单位为分
//获取prepayId(预支付交易会话标识)
NSString *prePayid;
prePayid = [self sendPrepay:packageParams];
if
(prePayid == nil)
{
[self.debugInfo appendFormat:@获取prepayid失败!
];
return
nil;
}
//获取到prepayid后进行第二次签名
NSString *package, *time_stamp, *nonce_str;
//设置支付参数
time_t now;
time(&now);
time_stamp = [NSString stringWithFormat:@%ld, now];
nonce_str = [WXUtil md5:time_stamp];
//重新按提交格式组包,微信客户端暂只支持package=Sign=WXPay格式,须考虑升级后支持携带package具体参数的情况
//package = [NSString stringWithFormat:@Sign=%@,package];
package = @Sign=WXPay;
//第二次签名参数列表
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject: self.appId forKey:@appid];
[signParams setObject: self.mchId forKey:@partnerid];
[signParams setObject: nonce_str forKey:@noncestr];
[signParams setObject: package forKey:@package];
[signParams setObject: time_stamp forKey:@timestamp];
[signParams setObject: prePayid forKey:@prepayid];
//生成签名
NSString *sign = [self createMd5Sign:signParams];
//添加签名
[signParams setObject: sign forKey:@sign];
[self.debugInfo appendFormat:@第二步签名成功,sign=%@
,sign];
//返回参数列表
return
signParams;
}
@end</code>
|
然后,在需要调用微信支付的Controller里面,新建一个方法。在合适的地方调用。这个方法里面利用WechatPayManager这个类进行了初始化和参数封装,然后把上述的核心代码(PayReq那一段) 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
<code
class
=
"hljs"
objectivec=
""
>- (
void
)wxPayWithOrderName:(NSString*)name price:(NSString*)price
{
//创建支付签名对象 && 初始化支付签名对象
WechatPayManager* wxpayManager = [[[WechatPayManager alloc]initWithAppID:APP_ID mchID:MCH_ID spKey:PARTNER_ID] autorelease];
//获取到实际调起微信支付的参数后,在app端调起支付
//生成预支付订单,实际上就是把关键参数进行第一次加密。
NSString* device = [[UserManager defaultManager]userId];
NSMutableDictionary *dict = [wxpayManager getPrepayWithOrderName:name
price:price
device:device];
if
(dict == nil){
//错误提示
NSString *debug = [wxpayManager getDebugInfo];
return
;
}
NSMutableString *stamp = [dict objectForKey:@timestamp];
//调起微信支付
PayReq* req = [[[PayReq alloc] init]autorelease];
req.openID = [dict objectForKey:@appid];
req.partnerId = [dict objectForKey:@partnerid];
req.prepayId = [dict objectForKey:@prepayid];
req.nonceStr = [dict objectForKey:@noncestr];
req.timeStamp = stamp.intValue;
req.package = [dict objectForKey:@package];
req.sign = [dict objectForKey:@sign];
// BOOL flag = [WXApi sendReq:req];
BOOL flag = [WXApi safeSendReq:req];
}</code>
|
再者,支付完成了需要调用一个delegate,这个delegate方便个性化显示支付结果。一般直接把这两个delegate放在AppDelegate就好了。因为有一些其他内容也是需要在AppDelegate里面实现,省的分开找不到.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<code
class
=
"hljs"
objectivec=
""
>-(
void
) onResp:(BaseResp*)resp
{
//启动微信支付的response
NSString *strMsg = [NSString stringWithFormat:@errcode:%d, resp.errCode];
if
([resp isKindOfClass:[PayResp
class
]]){
//支付返回结果,实际支付结果需要去微信服务器端查询
switch
(resp.errCode) {
case
0:
strMsg = @支付结果:成功!;
break
;
case
-1:
strMsg = @支付结果:失败!;
break
;
case
-2:
strMsg = @用户已经退出支付!;
break
;
default
:
strMsg = [NSString stringWithFormat:@支付结果:失败!retcode = %d, retstr = %@, resp.errCode,resp.errStr];
break
;
}
}
}</code>
|
注意事项:
1)如果APP里面已经使用了ShareSDK,就有一些地方要注意。不要再重复导入微信的SDK,因为shareSDK里面的extend已经包括了微信的SDK.
2)微信本身是鼓励客户APP把签名算法放到服务器上面,这样信息就不容易被破解。但是如果客户APP本身没有服务器端,或者认为不需要放到服务器端,也可以直接把签名(加密)的部分直接放在APP端。Sample代码的注释有点乱,多次提到服务器云云,但是其实可以不这么做.
3)微信的price单位是分。注意下即可.
4)暂时想不到,以后想到了再记录。.
以上是本文给大家叙述的IOS客户端接入微信支付的全部内容,希望大家喜欢.
最后此篇关于IOS客户端接入微信支付的文章就讲到这里了,如果你想了解更多关于IOS客户端接入微信支付的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在哪里可以找到有关退款状态的信息? 对于“取消”和“失败”,没关系。但是“已捕获”、“已授权”、“暂停”和“待处理”之间有什么区别。支付宝是什么意思? 谢谢 最佳答案 以下是 Paypal 付款状态列
我想问问是否有人知道无需用户交互即可进行 PayPal 付款的可能性。我目前正在开展一个项目,我们希望在用户无需登录 PayPal 的情况下按需进行 PayPal 付款。 我发现的是: 做引用交易 定
我无法找到 PayPal 提供的关于它如何处理 webhook 以进行支付的文档。付款是否与付款一样对待,以便完成的付款将启动付款完成的 webhook?一般来说,付款和支出是否通过网络 Hook 相
我有一个表单,人们可以在其中以固定金额订购一件商品。以下是步骤: 客户填写表格 客户点击提交并进入评论页面,他可以在其中检查他的输入 在评论表单中应该有一个使用 paypal 支付的按钮(带有自己的设
用了微信sdk各种痛苦,感觉比qq sdk调用麻烦多了,回调过于麻烦,还必须要在指定包名下的actvity进行回调,所以我在这里写一篇博客,有这个需求的朋友可以借鉴一下,以后自己别的项目有用到也有个
这个问题已经有答案了: 已关闭10 年前。 Possible Duplicate: How to set Azure Max Spending Limit or Cost CAP $ amount?
我正在尝试将 Stripe 集成到 Symfony2 项目上,我在他们的文档中看到的唯一付款方式是“用卡付款”按钮 https://stripe.com/docs/checkout它在我的项目上创建了
这个问题已经有答案了: 已关闭10 年前。 Possible Duplicate: How to set Azure Max Spending Limit or Cost CAP $ amount?
我想使用 firebase 作为服务器并向 stripe 发送付款请求。我在服务器端的经验为零,所以我正在寻找一种简单的方法来实现这一目标。此帖Is it possible to integrate
我在这里使用自适应 Paypal 支付控制台:https://apigee.com/console/paypal向人们付款。我无法找到一种方法在不授予他们许可的情况下向个人汇款(来 self )。我希
我一直坚持使用 OpenCart 的 PayPal 标准付款,但尚未找到解决方案。 我做了什么: 在 sandbox.paypal.com 上创建了企业帐户 设置以下网络首选项: 自动返回(指定 UR
我想在我的 WPF 应用程序中通过 PayPal 进行购物付款。我想为用户生成一个链接,但不知道如何通知应用程序已接受付款。是否唯一的解决方案将是服务器,它会检查付款是否已被接受并且应用程序会不时轮询
PayPal PayOut REST API 没有记录它的局限性。什么是: 每次付款的最大收款人数? 每次付款的最高金额? 每个收件人的最大金额? 注意: 我查看了在线文档和 paypal 论坛 (
我是 web 开发的新手,我需要做的是创建一个表单,用户可以在其中输入一些东西到一个字段中,让我们暂时称之为名称......然后当他们去 paypal 时,他们会捐赠 1 美元(预定)然后从支付给 P
我正在尝试将 PayPal 集成到我的应用程序中并了解 PayPal SDK 的工作原理我正在使用示例应用程序。我知道在用户按下“购买”按钮后,我需要将授权响应发送到我的服务器以验证付款。问题是我找不
在我的 oscar 应用程序中,django 需要自适应并行 oscar 支付程序。 谁能告诉我如何将 Adaptive Parallel Paypal 方法集成到 Normal Paypal 中。我
您好,我正在开发用于 NFC 支付的安卓应用程序。 Android 设置中有一个选项可以使用打开的应用程序而不是默认应用程序。例如,当我将默认应用程序设置为 Android Pay 并在付款前打开我的
我构建了一个使用命名空间和 PSR-0 自动加载的 PHP 应用程序。在尝试实现 Stripe库,我发现它似乎无法加载类,因为它们没有命名空间。如果我手动包含文件,有没有办法不自动加载? // Get
有人成功地将 Adyen 支付插件集成到 iOS 应用程序中吗? 我到了它向用户显示付款选项的地步,但选择其中一个选项没有任何作用。我希望它会转到表单以捕获卡的详细信息,但事实并非如此。 如有任何帮助
我正在与 Stripe Payment Gateway 集成——API 的最新版本。 除了“client_reference_id”没有传递给 webhook 或事务(没有出现在日志中)之外,这一切都
我是一名优秀的程序员,十分优秀!